目录
第一步——初步设计多文件
第二步——main函数的简单实现&&菜单函数的建立
菜单函数
第三步——游戏函数的开始建立及打印棋盘函数的编写
3.1 game函数
3.1.1 test.c文件内game函数:
3.2 初始化函数:
3.2.1 game.h内初始化函数
3.2.2 game.c内初始化函数
3.2.3 test.c内初始化函数
3.3 动态修改棋盘规模
3.3.1 game.h文件里对行、列进行宏定义:
3.3.2 在test.c文件内引用game.h头文件,并修改对应的数组行、列:
3.4 display_board函数
3.4.1 game.h 内display_board函数
3.4.2 game.c内display_board函数
3.4.3 test.c内display_board函数
3.5 修改
3.5.1 分割线
3.5.2 棋盘动态规模
第四步——下棋
4.1 玩家下棋:
4.1.1 game.h
4.1.2 game.c
4.2 电脑随机下棋
4.2.1 game.c
4.2.2 game.h
4.2.3 test.c
第五步——游戏结束的判定
5.1 is_win函数
5.1.1 test.c内
5.1.2 game.c内
5.2 is_full函数
game.c内
六——附代码
6.1 test.c
6.2 game.c
6.3 game.h
第一步——初步设计多文件
test.c用于测试代码(包括main函数;
game.h用于三子棋游戏的函数声明;
game.c用于游戏函数的实现;
game.h与game.c被test.c调用,从而实现三子棋游戏。
第二步——main函数的简单实现&&菜单函数的建立
游戏首先得打印出来,玩家开始选择玩or不玩,或者玩完一局之后继续玩。于是我们可以初步使用do-while 语句来实现游戏的开始,并且为了使游戏的各步设想更加独立化,我们会使用更多的自定义函数代码块。我们为该设计游戏简易菜单,如下:
//菜单函数 void menu() { printf("******************\n"); printf("***** 1.play *****\n"); printf("***** 0.exit *****\n"); printf("******************\n"); }
//主函数 int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择有误,请重新选择!\n"); break; } } while (input); return 0; }
第三步——游戏函数的开始建立及打印棋盘函数的编写
void game() { printf("三子棋游戏\n"); }
为了打印棋盘,我们设置3*3的数组棋盘( char board[3][3] )来实现九宫格的打印:
//需要3*3的数组char board[3][3] char board[3][3] = { 0 };
//初始化棋盘 void init_board(char board[ROW][COL], int row, int col);
void init_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }
void game() { //需要3*3的数组char board[3][3] char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); }
为了便于修改棋盘的规模,以便以后可以实现5*5,10*10等的棋盘,我们可以改进如下:
3.3.1 game.h文件里对行、列进行宏定义:
#define ROW 3 #define COL 3
3.3.2 在test.c文件内引用game.h头文件,并修改对应的数组行、列:
#include "game.h"
//游戏函数 void game() { //需要3*3的数组char board[3][3] char board[ROW ][COL] = { 0 }; }
为了打印出棋盘图像,我们引用函数display_board来打印棋盘
在game.h头文件内对函数进行声明:
void display_board(char board[ROW][COL], int row, int col);
在game.c文件对函数进行实现:
void display_board(char board[ROW][COL], int row, int col) { int i = 0,j=0; for (i = 0; i < row; i++) { //为了更美观在打印的前后加上空格,使棋盘看起来更松散,增加视觉舒适感 printf(" %c | %c | %c \n", board[i][0],board[i][1],board[i][2]); //换行 printf("---|---|---\n"); } }
在test.c内调用函数:
void game() { //需要3*3的数组char board[3][3] char board[ROW][COL] = { 0 }; init_board(board, ROW, COL); display_board(board, ROW , COL); }
运行如下:
我们对其再加工修改,使其去掉最后一行的分割线,如下:
当ROW、COL数据被修改之后,我们希望仍能打印出相应的5*5、10*10等棋盘,修改如下:
修该宏定义的ROW、COL可打印 5*5的棋盘:
第四步——下棋
//玩家下棋 void play_move(char board[ROW][COL], int row, int col);
void play_move(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家下棋:>\n"); while (1) { printf("请输入下棋的坐标:>"); scanf("%d %d", &x, &y); //1.坐标合法性 //2.坐标是否被占用 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标被占用,请重新输入\n"); } } else { printf("坐标非法,请重新输入\n"); } } }
//电脑随机下棋 void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); while (1) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
#include
#include //电脑下棋 void computer_move(char board[ROW][COL],int row,int col);
//游戏函数 void game() { //需要3*3的数组char board[3][3] char board[ROW][COL] = { 0 }; init_board(board, ROW, COL); display_board(board, ROW , COL); //玩游戏 while (1) { play_move(board, ROW, COL); display_board(board, ROW, COL); computer_move(board, ROW, COL); display_board(board, ROW, COL); } } int main() { int input = 0; srand((unsigned int)time(NULL)); //生成随机数 do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择有误,请重新选择!\n"); break; } } while (input); return 0; }
第五步——游戏结束的判定
//玩家赢-‘*’
//电脑赢-‘#’
// 平局-‘Q’
// 游戏继续-‘C’
void game()
{
char ret = 0;
//需要3*3的数组char board[3][3]
char board[ROW][COL] = { 0 };
init_board(board, ROW, COL);
display_board(board, ROW , COL);
//玩游戏
while (1)
{
play_move(board, ROW, COL);
ret=is_win(board, ROW, COL);
if (ret != 'C')
break;
display_board(board, ROW, COL);
computer_move(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
display_board(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if(ret == '#')
{
printf("电脑赢\n");
}
else if(ret=='Q')
{
printf("平局\n");
}
}
char is_win(char board[ROW][COL], int row, int col) { int i = 0; //行同,且均不为空格 for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ') { //可用if-else判断元素*or#,再分别return,但可以简单返回 return board[i][0]; } } //列同,且均不为空格 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ') { //可用if-else判断元素*or#,再分别return,但可以简单返回 return board[0][i]; } } //对角线 if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ') { //可用if-else判断元素*or#,再分别return,但可以简单返回 return board[0][0]; } if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != ' ') { //可用if-else判断元素*or#,再分别return,但可以简单返回 return board[0][2]; } //平局 if (is_full(board, row, col) == 1) { return 'Q'; } //继续 return 'C'; }
//如果棋盘满了,返回1; //不满返回0; 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; }
六——附代码