C语言 -- 三子棋
本篇主要是用二维数组和多个函数来实现三子棋游戏。
让我们先来看看这个编写这个游戏的思路:首先要打印三子棋的棋盘,然后是玩家下棋,电脑下棋,最后判断谁赢了,或者看看是否平局。
我们用一个头文件 game.h ,一个源文件 game.c(主要的代码都在这里面哦!)和一个源文件测试文件 text.c(主要写整个游戏的具体思路)来编写我们的代码。
*首先我们看看头文件(game.h):
#ifndef __GAME_H__ #define __GAME_H__ #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 //行 自己可以改变棋盘的大小 #define COL 3 //列 同上(不能小于三哦) void init_board(char board[ROW][COL], int row, int col); void print_board(char board[ROW][COL], int row, int col); void player_move(char board[ROW][COL], int row, int col); void computer_board(char board[ROW][COL], int row, int col); char is_win(char board[ROW][COL], int row, int col); //以上是后面源文件中需要调用的函数 enum OPTION { EXIT, PLAY }; //枚举 #endif // ! __GAME_H__
*再来看看测试文件 (test.c):
#include"game.h" void menu() { printf(" 三子棋游戏 \n"); printf("\n"); printf("***********************************\n"); printf("******* 1. play *******\n"); printf("******* 0. exit *******\n"); printf("***********************************\n"); } void game() { int row = 0; int col = 0; char ret = '0'; char board[ROW][COL] = { '0' }; //创建一个数组(棋盘) init_board(board, ROW, COL); //初始化棋盘,使其都是空格。 print_board(board, ROW, COL); //打印棋盘 while (1) { player_move(board, ROW, COL); //玩家下棋 print_board(board, ROW, COL); ret = is_win(board, ROW, COL); //判断输赢平局 if (ret == 'X') { printf("恭喜你,赢了!\n"); break; } else if (ret == 'Q') { printf("平局\n"); break; } computer_board(board, ROW, COL); //电脑下棋 print_board(board, ROW, COL); ret = is_win(board, ROW, COL); //判断 if (ret == 'O') { printf("电脑赢了!\n"); break; } else if (ret == 'Q') { printf("平局\n"); break; } } } int main() { int input = 0; srand((unsigned int)(time(NULL))); menu(); //打印菜单 do { printf("请选择:"); scanf_s("%d", &input); switch (input) { case PLAY: game(); break; case EXIT: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择!\n"); break; } } while (input); return 0; }
*最后来看看最重要的 game.c ,让我们分部来看:
初始化数组,元素都是空格
void init_board(char board[ROW][COL], int row, int col) { memset(board, ' ', sizeof(board[0][0]) * row * col); }
不知道memset函数的点击这里 ==> 点击打开链接
接下来就要打印棋盘了,如下图(3*3棋盘),我们将它分成后面这个图看看。
看红色的(横着看),发现最后一个红框里面比前面的少一个 ‘ | ’;
再看紫色的,发现最后一行比上面少底下一行;
观察完了,我们来实现代码
void print_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < col; i++) { for (j = 0; j < row; j++) { printf(" %c ", board[i][j]); if (j != row - 1) { printf("|"); } } printf("\n"); if (i != col - 1) { for (j = 0; j < row; j++) { printf("---"); if (j != row - 1) { printf("|"); } } printf("\n"); } } }
*玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家走\n");
printf("请输入你要下棋的坐标:");
scanf_s("%d %d", &x, &y);
if (((x > 0) && (x <= row)) && ((y > 0) && (y <= col))) //下棋的坐标要在棋盘内。
{
if (board[x - 1][y - 1] == ' ') //注:玩家输入的坐标假如是(1 1),写代码的应该知道其实是(0 0)
{
board[x - 1][y - 1] = 'X';
break;
}
else
{
printf("输入的坐标已有棋子,请重新输入!\n");
}
}
else
{
printf("输入棋子的坐标有误,请重新输入!\n");
}
}
}
*电脑下棋
void computer_board(char board[ROW][COL], int row, int col) { printf("电脑走\n"); while (1) { int x = rand() % row; //srand((unsigned int)(time(NULL)) int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = 'O'; break; } } }
*判断输赢还有平局
char is_win(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; for (x = 1; x < row - 1; x++) { for (y = 0; y < col; y++) { if ((board[x][y] == board[x - 1][y]) && (board[x][y] == board[x + 1][y]) && board[x][y] != ' ') { return board[x][y]; } } } for (x = 0; x < row; x++) { for (y = 1; y < col - 1; y++) { if ((board[x][y] == board[x][y - 1]) && (board[x][y] == board[x][y + 1]) && board[x][y] != ' ') { return board[x][y]; } } } for (x = 1; x < row - 1; x++) { for (y = 1; y < col - 1; y++) { if (((board[x][y] == board[x - 1][y - 1]) && (board[x][y] == board[x + 1][y + 1]) && board[x][y] != ' ') || ((board[x][y] == board[x - 1][y + 1]) && (board[x][y] == board[x + 1][y - 1])) && board[x][y] != ' ') return board[x][y]; } } if (is_full(board, ROW, COL) == 1) //判断棋盘是否满了(平局) { return 'Q'; //表示棋盘满了 } }
static int is_full(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; }
想想上面那段代码可以优化吗?
我们可以把玩家或者电脑下棋的坐标传过来,以这个坐标为中心判断输赢,就不用重新一个一个的找,一个一个判断。(可以自己试试哦!)
最后我们来看看结果(3*3棋盘)
再来看一个(5*5棋盘)
好了,这样这个三子棋代码就完成了!学会了吗?