今天呢,给小伙伴们分享一个比较容易上手的小游戏《三子棋》~
在创作这个小游戏之前呢,我们首先得分析一下这个游戏,让自己大脑有一个清晰的思路。先剖析游戏界面的布局,游戏实现,游戏输赢判断规则以及游戏玩法,再接着一步一步用代码的形式呈现出来。嘿嘿,那咱们就开始吧!(完整码源在最后)
一.概述
咱们先创建一个项目,然后再细分成源文件和头文件,这样方便咱们检查以及调用。
可以提前将需要的函数和库函数放入新创建的头文件,后续在源文件中需要使用时就可以直接引用新创建的头文件,这样比较方便和简洁。然后呢,咱们根据提前设定好的思路,一步一步将这些功能以代码形式实现。
#define ROW 3 //宏定义棋盘行数和列数
#define COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//头文件中声明函数
//初始化棋盘
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_move(char board[ROW][COL], int row, int col);
//判断输赢的函数
char is_win(char board[ROW][COL], int row, int col);
二.游戏界面的实现
首先咱们可以创造一个简易的游戏开始界面,提醒玩家这是三子棋游戏,然后引导玩家进行游戏。
这里咱们可以用一个简单的函数来单独实现,方便后续的调整
void menu() //不需要传入参数和返回值,所以用void形式就可以了
{
printf("********** 三子棋 **********\n");
printf("****************************\n");
printf("********* 1 - play *********\n"); //输入1即可开始游戏
printf("********* 0 - exit *********\n"); //输入0 则退出游戏
printf("****************************\n");
}
使用一个自定义的test函数来接受menu()函数,并且在里面实现是否游戏的功能。
void test()
{
srand((unsigned int)time(NULL));
again2:
printf("是否继续游戏?\n");
menu();
int input = 0;
again:
printf("请选择是否游戏-> : ");
scanf("%d", &input);
while (1)
{
if (input == 1)
{
game();
goto again2;
}
else if (input == 0)
{
printf("退出游戏!\n");
break;
}
else
{
printf("请重新选择!\n");
goto again;
}
}
}
紧接着就可以创作棋盘了。咱们可以用朴素的形式实现棋盘,通过 "___"
和“ | ”就可以了。这里用两个单独的函数以及循环语句来实现 。
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 print_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++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("___");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
这个就是棋盘实现效果。
制作好棋盘后,就可以进行游戏实现了。
三.游戏实现
下棋其实就像填空一样,哪里有空位置,棋子就可以落在哪里。而位置就用坐标来代替。咱们可以通过二维数组的形式来实现,包括刚才制作棋盘,也使用了二维数组。这里呢,先穿插一下游戏玩法,可以人机对战和人人对战,咱们这里先用人机对战为例子,来介绍游戏实现的方法。
首先先从玩家的角度出发。作为游戏玩家,当看到游戏棋盘的时候,填入的坐标一般是大众化的形式以(1,1)开始,而二维数组是从(0,0)开始,所以咱们得提前设定好。咱们可以用一个单独的函数来实现玩家下棋的功能,通过代码咱们可以看到,玩家的棋子将会以“ * ”的形式出现在棋盘上。通过while 循环的方法将玩家输入的坐标呈现到棋盘上,如果玩家输入的坐标不在棋盘的范围内,系统将会提醒玩家重新输入!
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋\n");
printf("请输入你想下棋的坐标\n");
while (1)
{
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标已使用,请重新输入\n");
}
else
printf("请输入规范的坐标\n");
}
}
运行演示
接着就是电脑实现下棋。想让电脑实现下棋,也得给它一个具体的坐标,但是这个坐标需要它自动生成,并且是随机的,那怎么办呢?这里咱们可以发挥聪明的脑瓜,利用电脑上能产生随机数的功能。这个就是时间了,因为它每时每刻都在变化。C语言的函数库中有<time.h>和<stdlib.h>库函数,调用它们,然后再利用 srand((unsigned int)time(NULL))函数就可以生成随机值,在棋盘上以“ # ” 的形式作为棋子,直接看代码吧~
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑棋子为 # \n");
while (1)
{
printf("电脑下棋\n");
int x = rand() % row; // %: 使生成的值为 0,1,2
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
运行演示
四.游戏输赢判断规则
三子棋的游戏规则就是看谁的棋子能够在横\竖\对角线的位置实现连接,不被打断。所以咱们可以根据这个逻辑,进行代码实现。但是也需要考虑棋下到最后,棋盘满了,谁都没能赢的情况,也就是平局。
//判断棋盘是否还有空位置,如果没有,且没决出胜负,则为平局
int is_full(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++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
//游戏判断规则
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][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局?
if (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
//没有玩家或者电脑赢,也没有平局,游戏继续
return 'C';
}
最后呢,咱们可以将这些函数功能,通过调用,都实现在咱们自己定义的game()函数中
void game()
{
char board[ROW][COL];
char ret = 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 != 'C')
{
break;
}
computer_move(board, ROW, COL);
print_board(board, ROW, COL);
//判断输赢
ret = is_win(board, ROW, COL); //电脑下棋功能
if (ret != 'C')
{
break;
}
}
//根据判断函数返回值判断输赢
if (ret == '#')
{
printf("电脑赢了\n");
}
else if (ret == '*')
{
printf("玩家赢了\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
}
运行演示
五.玩法扩展
如果想和身边小伙伴一起玩的话,可以将电脑下棋的函数替换成玩家2的函数,具体操作就是在咱们自定义的头文件中,加入玩家2函数,然后玩家2下棋规则以及判断输赢规则都一样,这里小伙伴们可以自己动手来实现这一功能。
//玩家2函数
void player2_move(char board[ROW][COL], int row, int col)
{
printf("玩家2下棋\n");
printf("请输入你想下棋的坐标\n");
while (1)
{
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("坐标已使用,请重新输入\n");
}
else
printf("请输入规范的坐标\n");
}
}
六.小小提醒
在写代码过程中,咱们一定得先理清思路,这样才能有条不紊的实现代码功能,不然容易半路卡壳,还有就是函数的使用,要考虑好是否需要返回值以及其类型,传入参数,函数内部逻辑。在使用循环和选择语句时,这个 “ {} ”的使用一定要清晰,不然代码很容易就不按你的思路运行了。
最后,看懂代码和会写是完全不一样的,所以实践很重要!
祝小伙伴们早日成为技术大牛@
///自定义头文件
#define ROW 3
#define COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//头文件中声明函数
//初始化棋盘
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_move(char board[ROW][COL], int row, int col);
//判断输赢的函数
char is_win(char board[ROW][COL], int row, int col);
///游戏实现源文件
#include "game.h"
void menu() //不需要传入参数和返回值,所以用void形式就可以了
{
printf("********** 三子棋 **********\n");
printf("****************************\n");
printf("********* 1 - play *********\n");
printf("********* 0 - exit *********\n");
printf("****************************\n");
}
void game()
{
char board[ROW][COL];
char ret = 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 != 'C')
{
break;
}
computer_move(board, ROW, COL);
print_board(board, ROW, COL);
//判断输赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '#')
{
printf("电脑赢了\n");
}
else if (ret == '*')
{
printf("玩家赢了\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
}
void test()
{
srand((unsigned int)time(NULL));
again2:
printf("是否继续游戏?\n");
menu();
int input = 0;
again:
printf("请选择是否游戏-> : ");
scanf("%d", &input);
while (1)
{
if (input == 1)
{
game();
goto again2;
}
else if (input == 0)
{
printf("退出游戏!\n");
break;
}
else
{
printf("请重新选择!\n");
goto again;
}
}
}
int main()
{
test();
return 0;
}
///游戏内部源文件
#include "game.h"
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 print_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++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("___");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋\n");
printf("请输入你想下棋的坐标\n");
while (1)
{
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && 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)
{
printf("电脑下棋\n");
int x = rand() % row; // %: 使生成的值为 0,1,2
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判断棋盘是否还有空位置,如果没有,且没决出胜负,则为平局
int is_full(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++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
//游戏判断规则
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][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局?
if (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
//没有玩家或者电脑赢,也没有平局,游戏继续
return 'C';
}