Compare commits
No commits in common. "714dc3dbdb640310c636e14e184cf3d4d76f0e63" and "1b1a63e78c3acbeac2951d52ccab4a37cde3e4eb" have entirely different histories.
714dc3dbdb
...
1b1a63e78c
@ -1,14 +1,80 @@
|
|||||||
CC = gcc
|
#include <stdio.h>
|
||||||
CFLAGS = -Wall -Wextra -std=c99
|
#include <stdlib.h>
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
all: game
|
#define WIDTH 11
|
||||||
|
#define HEIGHT 11
|
||||||
|
|
||||||
game: game.c world.o
|
typedef enum {EMPTY, CROSS, CIRCLE} Cell;
|
||||||
$(CC) $(CFLAGS) -o game game.c world.o
|
|
||||||
|
|
||||||
world.o: world.c world.h
|
Cell board[HEIGHT][WIDTH] = {EMPTY};
|
||||||
$(CC) $(CFLAGS) -c world.c
|
|
||||||
|
|
||||||
clean:
|
void draw_board() {
|
||||||
rm -f game world.o
|
clear_world();
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
int world_x = x * 2 + 1;
|
||||||
|
int world_y = y * 2 + 1;
|
||||||
|
if (board[y][x] == CROSS) {
|
||||||
|
draw_character('X', world_x, world_y);
|
||||||
|
} else if (board[y][x] == CIRCLE) {
|
||||||
|
draw_character('O', world_x, world_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh_world();
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_win(Cell player) {
|
||||||
|
// Check rows
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
int count = 0;
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
if (board[y][x] == player) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
if (count == 5) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check columns
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
int count = 0;
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
if (board[y][x] == player) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
if (count == 5) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Implement diagonal checks
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
init_world(2 * WIDTH + 1, 2 * HEIGHT + 1);
|
||||||
|
draw_board();
|
||||||
|
int turn = 0;
|
||||||
|
while (1) {
|
||||||
|
int x, y;
|
||||||
|
printf("Player %d's turn. Enter coordinates (x y): ", turn % 2 + 1);
|
||||||
|
scanf("%d %d", &x, &y);
|
||||||
|
if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT && board[y][x] == EMPTY) {
|
||||||
|
board[y][x] = (turn % 2 == 0) ? CROSS : CIRCLE;
|
||||||
|
draw_board();
|
||||||
|
if (check_win(board[y][x])) {
|
||||||
|
printf("Player %d wins!\n", turn % 2 + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
turn++;
|
||||||
|
} else {
|
||||||
|
printf("Invalid move. Try again.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close_world();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
# Tetris Game
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
This is a simple implementation of the classic Tetris game. The player controls falling tetrominoes to create complete lines, which then disappear. The game ends when the tetrominoes stack up to the top of the screen.
|
|
||||||
|
|
||||||
## How to Build and Run
|
|
||||||
|
|
||||||
1. Ensure you have a C compiler installed on your system.
|
|
||||||
2. Clone the repository and navigate to the directory containing the source code.
|
|
||||||
3. Compile the game using the provided Makefile:
|
|
||||||
|
|
80
final/final.c
Normal file
80
final/final.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
#define WIDTH 11
|
||||||
|
#define HEIGHT 11
|
||||||
|
|
||||||
|
typedef enum {EMPTY, CROSS, CIRCLE} Cell;
|
||||||
|
|
||||||
|
Cell board[HEIGHT][WIDTH] = {EMPTY};
|
||||||
|
|
||||||
|
void draw_board() {
|
||||||
|
clear_world();
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
int world_x = x * 2 + 1;
|
||||||
|
int world_y = y * 2 + 1;
|
||||||
|
if (board[y][x] == CROSS) {
|
||||||
|
draw_character('X', world_x, world_y);
|
||||||
|
} else if (board[y][x] == CIRCLE) {
|
||||||
|
draw_character('O', world_x, world_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh_world();
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_win(Cell player) {
|
||||||
|
// Check rows
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
int count = 0;
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
if (board[y][x] == player) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
if (count == 5) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check columns
|
||||||
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
|
int count = 0;
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
if (board[y][x] == player) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
if (count == 5) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Implement diagonal checks
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
init_world(2 * WIDTH + 1, 2 * HEIGHT + 1);
|
||||||
|
draw_board();
|
||||||
|
int turn = 0;
|
||||||
|
while (1) {
|
||||||
|
int x, y;
|
||||||
|
printf("Player %d's turn. Enter coordinates (x y): ", turn % 2 + 1);
|
||||||
|
scanf("%d %d", &x, &y);
|
||||||
|
if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT && board[y][x] == EMPTY) {
|
||||||
|
board[y][x] = (turn % 2 == 0) ? CROSS : CIRCLE;
|
||||||
|
draw_board();
|
||||||
|
if (check_win(board[y][x])) {
|
||||||
|
printf("Player %d wins!\n", turn % 2 + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
turn++;
|
||||||
|
} else {
|
||||||
|
printf("Invalid move. Try again.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close_world();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
132
final/game.c
132
final/game.c
@ -1,132 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "world.h"
|
|
||||||
|
|
||||||
#define EMPTY ' '
|
|
||||||
#define BLOCK '#'
|
|
||||||
#define WIDTH 10
|
|
||||||
#define HEIGHT 20
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int x, y;
|
|
||||||
} Point;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Point blocks[4];
|
|
||||||
Point position;
|
|
||||||
} Tetromino;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char grid[HEIGHT][WIDTH];
|
|
||||||
Tetromino current;
|
|
||||||
} GameState;
|
|
||||||
|
|
||||||
Tetromino tetrominoes[] = {
|
|
||||||
{{{0,0}, {1,0}, {0,1}, {1,1}}, {0,0}}, // Square
|
|
||||||
{{{0,0}, {1,0}, {2,0}, {3,0}}, {0,0}}, // Line
|
|
||||||
{{{0,0}, {1,0}, {1,1}, {2,1}}, {0,0}}, // Z shape
|
|
||||||
{{{1,0}, {2,0}, {0,1}, {1,1}}, {0,0}}, // S shape
|
|
||||||
{{{0,0}, {1,0}, {2,0}, {1,1}}, {0,0}}, // T shape
|
|
||||||
{{{0,0}, {0,1}, {1,1}, {2,1}}, {0,0}}, // L shape
|
|
||||||
{{{2,0}, {0,1}, {1,1}, {2,1}}, {0,0}} // J shape
|
|
||||||
};
|
|
||||||
|
|
||||||
void draw_grid(GameState* game) {
|
|
||||||
clear_world();
|
|
||||||
for (int y = 0; y < HEIGHT; ++y) {
|
|
||||||
for (int x = 0; x < WIDTH; ++x) {
|
|
||||||
draw_character(game->grid[y][x], x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
draw_character(BLOCK, game->current.position.x + game->current.blocks[i].x,
|
|
||||||
game->current.position.y + game->current.blocks[i].y);
|
|
||||||
}
|
|
||||||
refresh_world();
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_valid_position(GameState* game, Point new_position) {
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
int new_x = new_position.x + game->current.blocks[i].x;
|
|
||||||
int new_y = new_position.y + game->current.blocks[i].y;
|
|
||||||
if (new_x < 0 || new_x >= WIDTH || new_y < 0 || new_y >= HEIGHT || game->grid[new_y][new_x] != EMPTY) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void place_tetromino(GameState* game) {
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
int x = game->current.position.x + game->current.blocks[i].x;
|
|
||||||
int y = game->current.position.y + game->current.blocks[i].y;
|
|
||||||
game->grid[y][x] = BLOCK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_lines(GameState* game) {
|
|
||||||
for (int y = HEIGHT - 1; y >= 0; --y) {
|
|
||||||
int full = 1;
|
|
||||||
for (int x = 0; x < WIDTH; ++x) {
|
|
||||||
if (game->grid[y][x] == EMPTY) {
|
|
||||||
full = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (full) {
|
|
||||||
for (int row = y; row > 0; --row) {
|
|
||||||
memcpy(game->grid[row], game->grid[row - 1], WIDTH);
|
|
||||||
}
|
|
||||||
memset(game->grid[0], EMPTY, WIDTH);
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* init_game() {
|
|
||||||
srand(time(NULL));
|
|
||||||
GameState* game = malloc(sizeof(GameState));
|
|
||||||
memset(game->grid, EMPTY, sizeof(game->grid));
|
|
||||||
game->current = tetrominoes[rand() % 7];
|
|
||||||
game->current.position.x = WIDTH / 2 - 1;
|
|
||||||
game->current.position.y = 0;
|
|
||||||
return game;
|
|
||||||
}
|
|
||||||
|
|
||||||
int game_event(struct event* event, void* state) {
|
|
||||||
GameState* game = (GameState*)state;
|
|
||||||
Point new_position = game->current.position;
|
|
||||||
|
|
||||||
if (event->key) {
|
|
||||||
switch (event->key) {
|
|
||||||
case 'a': new_position.x -= 1; break;
|
|
||||||
case 'd': new_position.x += 1; break;
|
|
||||||
case 's': new_position.y += 1; break;
|
|
||||||
case 'w': // TODO: Implement rotation
|
|
||||||
break;
|
|
||||||
case 27: return 1; // Escape key
|
|
||||||
}
|
|
||||||
if (is_valid_position(game, new_position)) {
|
|
||||||
game->current.position = new_position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new_position.y += 1;
|
|
||||||
if (!is_valid_position(game, new_position)) {
|
|
||||||
place_tetromino(game);
|
|
||||||
clear_lines(game);
|
|
||||||
game->current = tetrominoes[rand() % 7];
|
|
||||||
game->current.position.x = WIDTH / 2 - 1;
|
|
||||||
game->current.position.y = 0;
|
|
||||||
if (!is_valid_position(game, game->current.position)) {
|
|
||||||
return 1; // Game over
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
game->current.position = new_position;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_grid(game);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
#include <ncurses.h>
|
|
||||||
#include "world.h"
|
|
||||||
|
|
||||||
static int width, height;
|
|
||||||
|
|
||||||
void init_world(int w, int h) {
|
|
||||||
width = w;
|
|
||||||
height = h;
|
|
||||||
initscr();
|
|
||||||
noecho();
|
|
||||||
curs_set(FALSE);
|
|
||||||
timeout(100);
|
|
||||||
keypad(stdscr, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_world() {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_character(char c, int x, int y) {
|
|
||||||
mvaddch(y, x, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void refresh_world() {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
int world_width() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int world_height() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
#ifndef WORLD_H
|
|
||||||
#define WORLD_H
|
|
||||||
|
|
||||||
struct event {
|
|
||||||
int key;
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_world(int width, int height);
|
|
||||||
void clear_world();
|
|
||||||
void draw_character(char c, int x, int y);
|
|
||||||
void refresh_world();
|
|
||||||
int world_width();
|
|
||||||
int world_height();
|
|
||||||
|
|
||||||
#endif // WORLD_H
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user