⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntetris.c

📁 一个嵌入式操作系统(microwindows)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. *  * The Original Code is NanoTetris. *  * The Initial Developer of the Original Code is Alex Holden. * Portions created by Alex Holden are Copyright (C) 2000, 2002 * Alex Holden <alex@alexholden.net>. All Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the terms * of the GNU General Public license (the  "[GNU] License"), in which case the * provisions of [GNU] License are applicable instead of those * above.  If you wish to allow use of your version of this file only * under the terms of the [GNU] License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting  the provisions above and replace  them with the notice and * other provisions required by the [GNU] License.  If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the [GNU] License. *//* * A Nano-X Tetris clone by Alex Holden. * * The objective is to keep placing new pieces for as long as possible. When a * horizontal line is filled with blocks, it will vanish, and everything above * it will drop down a line. It quickly gets difficult because the speed * increases with the score. Unlike with some Tetris clones, no bonus points * are awarded for matching colours, completing more than one line at a time, * or for using the "drop shape to bottom" function. * * The box in the top left of the game window is the score box. The top score * is the highest score you have achieved since last resetting the high score * counter. The counter is stored when the game exits in the file specified by * the HISCORE_FILE parameter ("/usr/games/nanotetris.hiscore" by default).  * Note that no attempt is made to encrypt the file, so anybody with write * access to the file can alter the contents of it using a text editor. * * The box below the score box is the next shape box. This contains a "preview" * of the next shape to appear, so that you can plan ahead as you are building * up the blocks. * * The game functions can be controlled using either the mouse (or a touch pad, * touch screen, trackball, etc.) and the buttons below the next shape box, or * with the following keyboard keys: * *   Q = quit game *   N = new game *   P = pause game *   C = continue game *   D = rotate shape anticlockwise *   F = rotate shape clockwise *   J = move shape left *   K = move shape right *   Space Bar = drop shape to bottom. * * The reason for the unconventional use of D, F, J, and K keys is that they * are all in the "home" position of a QWERTY keyboard, which makes them very * easy to press if you are used to touch typing. * * I'll leave it to you to figure out which mouse operated movement button does * what (it's pretty obvious). */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <time.h>#include <ctype.h>#include <errno.h>#include <sys/time.h>#ifdef __ECOS#define random  rand#define srandom srand#endif#include <nano-X.h>#include <nxcolors.h>#include "ntetris.h"void *my_malloc(size_t size){	void *ret;	if(!(ret = malloc(size))) {		fprintf(stderr, "Out of memory\n");		exit(1);	}	return ret;}#ifdef HAVE_USLEEPvoid msleep(long ms){	usleep(ms * 1000);}#elsevoid msleep(long ms){	struct timespec req, rem;	req.tv_sec = ms / 1000000;	req.tv_nsec = (ms % 1000000) * 1000000;	while(nanosleep(&req, &rem) == -1) {		if(errno == EINTR) {			req.tv_sec = rem.tv_sec;			req.tv_nsec = rem.tv_nsec;			continue;		} else {			perror("nanosleep() failed");			return;		}	}}#endif#ifdef USE_HISCORE_FILEvoid read_hiscore(nstate *state){	FILE *f;	int i, n;	if(!(f = fopen(HISCORE_FILE, "r"))) {		if(errno != ENOENT)			perror("Couldn't open high score file for reading");		state->hiscore = state->fhiscore = 0;		return;	}	i = fscanf(f, "%d", &n);	fclose(f);	if(i != 1) {		fprintf(stderr, "Couldn't read high score file\n");		n = 0;	}	state->hiscore = state->fhiscore = n;}void write_hiscore(nstate *state){	FILE *f;	if(state->score > state->hiscore) state->hiscore = state->score;	if(state->hiscore <= state->fhiscore) return;	if(!(f = fopen(HISCORE_FILE, "w"))) {		perror("Couldn't open high score file for writing");		return;	}	if((fprintf(f, "%d", state->hiscore)) == -1)		perror("Couldn't write to high score file");	else state->fhiscore = state->hiscore;	fclose(f);}#elsevoid read_hiscore(nstate *state){	state->hiscore = 0;}void write_hiscore(nstate *state) {}#endifint will_collide(nstate *state, int x, int y, int orientation){	int r, c, xx, yy;	char ch = 0;	draw_shape(state, state->current_shape.x, state->current_shape.y, 1);	for(r = 0; ch < 3; r++) {		ch = 0;		for(c = 0; ch < 2; c++) {			ch = shapes[state->current_shape.type]				[orientation][r][c];			if(ch == 1) {				yy = y + r;				xx = x + c;				if((yy == WELL_HEIGHT) || (xx == WELL_WIDTH) ||						(state->blocks[0][yy][xx])) {					draw_shape(state,						state->current_shape.x,						state->current_shape.y, 0);					return 1;				}			}		}	}	draw_shape(state, state->current_shape.x, state->current_shape.y, 0);	return 0;}void draw_shape(nstate *state, GR_COORD x, GR_COORD y, int erase){	int r, c, yy, xx;	GR_COLOR col;	char ch = 0;	if(erase) col = 0;	else col = state->current_shape.colour;	for(r = 0; ch < 3; r++) {		ch = 0;		for(c = 0; ch < 2; c++) {			ch = shapes[state->current_shape.type]				[state->current_shape.orientation][r][c];			if(ch == 1) {				yy = y + r;				xx = x + c;				state->blocks[0][yy][xx] = col;			}		}	}}void draw_well(nstate *state, int forcedraw){	int x, y;	for(y = WELL_NOTVISIBLE; y < WELL_HEIGHT; y++) {		for(x = 0; x < WELL_WIDTH; x++) {			if(forcedraw || (state->blocks[0][y][x] !=						state->blocks[1][y][x])) {				state->blocks[1][y][x] = state->blocks[0][y][x];				GrSetGCForeground(state->wellgc,							state->blocks[0][y][x]);				GrFillRect(state->well_window, state->wellgc,					(BLOCK_SIZE * x),					(BLOCK_SIZE * (y - WELL_NOTVISIBLE)),						BLOCK_SIZE, BLOCK_SIZE);			}		}	}	GrFlush();}void draw_score(nstate *state){	char buf[32];	GrFillRect(state->score_window, state->scoregcb, 0, 0,			SCORE_WINDOW_WIDTH, SCORE_WINDOW_HEIGHT);	sprintf(buf, "%d", state->score);	GrText(state->score_window, state->scoregcf, TEXT_X_POSITION,					TEXT2_Y_POSITION, buf, strlen(buf), 0);	sprintf(buf, "%d", state->hiscore);	GrText(state->score_window, state->scoregcf, TEXT_X_POSITION,					TEXT_Y_POSITION, buf, strlen(buf), 0);}void draw_next_shape(nstate *state){	int r, c, startx, starty, x, y;	char ch = 0;	GrFillRect(state->next_shape_window, state->nextshapegcb, 0, 0,			NEXT_SHAPE_WINDOW_WIDTH, NEXT_SHAPE_WINDOW_HEIGHT);	GrSetGCForeground(state->nextshapegcf, state->next_shape.colour);	startx = (BLOCK_SIZE * ((NEXT_SHAPE_WINDOW_SIZE / 2) -			(shape_sizes[state->next_shape.type]			[state->next_shape.orientation][0] / 2)));	starty = (BLOCK_SIZE * ((NEXT_SHAPE_WINDOW_SIZE / 2) -			(shape_sizes[state->next_shape.type]			[state->next_shape.orientation][1] / 2)));	for(r = 0; ch < 3; r++) {		ch = 0;		for(c = 0; ch < 2; c++) {			ch = shapes[state->next_shape.type]				[state->next_shape.orientation][r][c];			if(ch == 1) {				x = startx + (c * BLOCK_SIZE);				y = starty + (r * BLOCK_SIZE);				GrFillRect(state->next_shape_window,					state->nextshapegcf, x, y,					BLOCK_SIZE, BLOCK_SIZE);			}		}	}}void draw_new_game_button(nstate *state){	GrFillRect(state->new_game_button, state->buttongcb, 0, 0,			NEW_GAME_BUTTON_WIDTH, NEW_GAME_BUTTON_HEIGHT);	GrText(state->new_game_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "New Game", 8, 0);}void draw_anticlockwise_button(nstate *state){	if(!state->running_buttons_mapped) return;	GrFillRect(state->anticlockwise_button, state->buttongcb, 0, 0,		ANTICLOCKWISE_BUTTON_WIDTH, ANTICLOCKWISE_BUTTON_HEIGHT);	GrText(state->anticlockwise_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "   /", 4, 0);}void draw_clockwise_button(nstate *state){	if(!state->running_buttons_mapped) return;	GrFillRect(state->clockwise_button, state->buttongcb, 0, 0,			CLOCKWISE_BUTTON_WIDTH, CLOCKWISE_BUTTON_HEIGHT);	GrText(state->clockwise_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "   \\", 4, 0);}void draw_left_button(nstate *state){	if(!state->running_buttons_mapped) return;	GrFillRect(state->left_button, state->buttongcb, 0, 0,			LEFT_BUTTON_WIDTH, LEFT_BUTTON_HEIGHT);	GrText(state->left_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "  <", 3, 0);}void draw_right_button(nstate *state){	if(!state->running_buttons_mapped) return;	GrFillRect(state->right_button, state->buttongcb, 0, 0,			RIGHT_BUTTON_WIDTH, RIGHT_BUTTON_HEIGHT);	GrText(state->right_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "   >", 4, 0);}void draw_drop_button(nstate *state){	if(!state->running_buttons_mapped) return;	GrFillRect(state->drop_button, state->buttongcb, 0, 0,			DROP_BUTTON_WIDTH, DROP_BUTTON_HEIGHT);	GrText(state->drop_button, state->buttongcf, TEXT_X_POSITION,					TEXT_Y_POSITION, "    Drop", 8, 0);}void draw_pause_continue_button(nstate *state){	if((state->running_buttons_mapped) && (state->state == STATE_STOPPED)) {		GrUnmapWindow(state->pause_continue_button);		GrUnmapWindow(state->anticlockwise_button);		GrUnmapWindow(state->clockwise_button);		GrUnmapWindow(state->left_button);		GrUnmapWindow(state->right_button);		GrUnmapWindow(state->drop_button);		state->running_buttons_mapped = 0;		return;	}	if((!state->running_buttons_mapped) && (state->state == STATE_RUNNING)){		GrMapWindow(state->pause_continue_button);		GrMapWindow(state->anticlockwise_button);		GrMapWindow(state->clockwise_button);		GrMapWindow(state->left_button);		GrMapWindow(state->right_button);		GrMapWindow(state->drop_button);		state->running_buttons_mapped = 1;		return;	}	if(!state->running_buttons_mapped) return;	GrFillRect(state->pause_continue_button, state->buttongcb, 0, 0,		PAUSE_CONTINUE_BUTTON_WIDTH, PAUSE_CONTINUE_BUTTON_HEIGHT);	if(state->state == STATE_PAUSED) {		GrText(state->pause_continue_button, state->buttongcf,			TEXT_X_POSITION, TEXT_Y_POSITION, " Continue", 9, 0);	} else {		GrText(state->pause_continue_button, state->buttongcf,			TEXT_X_POSITION, TEXT_Y_POSITION, "   Pause", 8, 0);	}}int block_is_all_in_well(nstate *state){	if(state->current_shape.y >= WELL_NOTVISIBLE)		return 1;	return 0;}void delete_line(nstate *state, int line){	int x, y;	if(line < WELL_NOTVISIBLE) return;	for(y = line - 1; y; y--)		for(x = WELL_WIDTH; x; x--)			state->blocks[0][y + 1][x] = state->blocks[0][y][x];	draw_well(state, 0);}void block_reached_bottom(nstate *state){	int x, y, nr;	if(!block_is_all_in_well(state)) {		state->state = STATE_STOPPED;		return;	}	for(y = WELL_HEIGHT - 1; y; y--) {		nr = 0;		for(x = 0; x < WELL_WIDTH; x++) {			if(!state->blocks[0][y][x]) {				nr = 1;				break;			}		}		if(nr) continue;		msleep(DELETE_LINE_DELAY);		delete_line(state, y);		state->score += SCORE_INCREMENT;		if((LEVELS > (state->level + 1)) && (((state->level + 1) *					LEVEL_DIVISOR) <= state->score))			state->level++;		draw_score(state);		y++;	}	choose_new_shape(state);	draw_next_shape(state);}void move_block(nstate *state, int direction){	if(direction == 0) { 		if(!state->current_shape.x) return;		else {			if(!will_collide(state, (state->current_shape.x - 1),						state->current_shape.y,					state->current_shape.orientation)) {				draw_shape(state, state->current_shape.x,						state->current_shape.y, 1);				state->current_shape.x--;				draw_shape(state, state->current_shape.x,						state->current_shape.y, 0);				draw_well(state, 0);			}		}	} else {		if(!will_collide(state, (state->current_shape.x + 1),						state->current_shape.y,					state->current_shape.orientation)) {			draw_shape(state, state->current_shape.x,					state->current_shape.y, 1);			state->current_shape.x++;			draw_shape(state, state->current_shape.x,					state->current_shape.y, 0);			draw_well(state, 0);		}	}}void rotate_block(nstate *state, int direction){	int neworientation = 0;	if(direction == 0) {		if(!state->current_shape.orientation)			neworientation = MAXORIENTATIONS - 1;		else neworientation = state->current_shape.orientation - 1;	} else {		neworientation = state->current_shape.orientation + 1;		if(neworientation == MAXORIENTATIONS) neworientation = 0;	}	if(!will_collide(state, state->current_shape.x, state->current_shape.y,							neworientation)) {		draw_shape(state, state->current_shape.x,				state->current_shape.y, 1);		state->current_shape.orientation = neworientation;		draw_shape(state, state->current_shape.x,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -