前言
在学习完数组相关的一些知识后,我们就可以来动手写属于自己的游戏程序了!这样学习起来感觉是不是充满了斗志呢?并且这可能是你游戏创作生涯的重要一步。
简单介绍
下面所实现的三子棋游戏程序完成了玩家先手,电脑后手的下棋步骤;
在开始菜单栏里,我们通过输入1或者0来选择开始游戏或退出游戏;
当然,这里实现的三子棋程序缺点多多,其中最致命的是电脑无法来进行有效的防御或进攻,这里电脑所下位置是在所剩空格处随机下棋(随机也是一种美),哈哈^ - ^
当然,实现哪些功能我们完全可以手写出来(即可以通过玩家所下棋位置进行当前最好的下棋位置的判断),我在这里必须膜拜一下阿尔法狗了~
我们在玩三子棋的时候可以发现,两个会下三子棋的人最终结果都是平局,所以这个程序还是有优点的,可以体验三子棋经常胜利的感觉!
当然,也希望各位大佬在评论区提出自己的见解和看法。
思路
在这里,我是应用多文件编程进行了三子棋程序的编写。
创建了game源文件,game头文件,test源文件。
不了解的可以了解多文件编程的优点。
一、编写主要框架
那我们先编写主函数完成主要框架的搭建吧
int main()
{
int input = 2;
do { //这里用do...while循环
menu(); //菜单栏0
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game(); //三子棋游戏
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
system("cls");
} while (input-2); //直接用到真值判断是否继续游戏
return 0;
}
开始菜单
void menu()
{
printf("******** 三子棋 ********\n");
printf("1.开始游戏 2.退出游戏\n");
printf("**************************\n");
}
二、初始化并打印棋盘
开始时我们先用define定义三子棋棋盘的行和列,这样会让接下来程序的编写更加轻松,也便于理解。
#define ROW 3
#define COL 3
接下来定义一个二维数组
char board[ROW][COL];
我们还要初始化三子棋棋盘的内容,因为在你不初始化数组时会发生意想不到的后果 > - <
void InitBoard(char board[ROW][COL], int row, int col)
{ //Init 初始化英文缩写
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
接下来我们需要打印出我们的棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//打印分割列
printf("|");
int j = 0;
for (j = 0; j < col; j++)
printf(" %c |", board[i][j]);
printf("\n");
//打印分割行
printf("---");
for (j = 0; j < col; j++)
printf("---");
printf("\n");
}
}
三、玩家下棋
接下来,我们让玩家下棋,函数实现如下:
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请下棋:>\n");
while (1) //这里用一个while循环让玩家下对为止
{
printf("请输入一个坐标,例:1 1>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= row)
{
if (board[x - 1][y - 1] != ' ')//当所下位置为空时,才能键入
printf("坐标被占用,请重新输入!\n");
else
{
board[x - 1][y - 1] = '*';
break;
}
}
else
printf("坐标非法,请重新输入!\n");//可能玩家会输入100 100,这当然也不行
}
}
四、电脑下棋
这里用到了一个随机数生成的函数,我们利用时间戳的唯一性来生成随机数。
srand((unsigned int)time(NULL)); //该行需要添加至合适位置,实现下面代码随机数的生成
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>");
while (1)
{
int x = rand() % row;//这里用到了生成随机数的功能
int y = rand() % col;//可以查查相关的资料,还可以看它
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
printf("%d %d\n",x,y);
}
}
五、判断回合阶段
现在需要进行回合阶段的判断,即 玩家胜、电脑胜、平局或者游戏继续的判断。
胜利的判断方法:查找是否有三个连续非空的 *
或 #
平局的判断方法:棋盘下满无胜出者
继续的判断方法:除去两者之外的情况则继续
char CheckWin(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 < row; 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[0][0] != ' ')
{
return board[1][1];
}
//平局
if (IsFull(board,row,col) == 1)//这里又调用IsFull函数
{
return 'E';
}
return 'C';
}
判断棋盘是否下满
int IsFull(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;
}
六、game()函数
完成了game()函数的各个功能,就可以整合在一起了
void game()
{
//数据的存储是二维数组
char board[ROW][COL];
//初始化棋盘-初始化为空格
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'C')
break;
DisplayBoard(board, ROW, COL);
//电脑下棋
ComputerMove(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'C')
break;
DisplayBoard(board, ROW, COL);
}
if (ret == '*')
printf("玩家赢!\n");
else if (ret == '#')
printf("电脑赢!\n");
else if (ret == 'E')
printf("平局\n");
}
最终代码
game.h
#define ROW 3
#define COL 3
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char CheckWin(char board[ROW][COL], int row, int col);
//电脑赢了 # 利用所用字符代表
//玩家赢了 *
//平局 E --even
//继续 C --continue
game.c
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{ //Init 初始化英文缩写
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
printf(" --- --- ---\n");
for (i = 0; i < row; i++)
{
//打印分割列
printf("|");
int j = 0;
for (j = 0; j < col; j++)
printf(" %c |", board[i][j]);
printf("\n");
//打印分割行
for (j = 0; j < col; j++)
printf(" ---");
printf("\n");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请下棋:>\n");
while (1) //这里用一个while循环让玩家下对为止
{
printf("请输入一个坐标,例:1 1>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= row)
{
if (board[x - 1][y - 1] != ' ')//当所下位置为空时,才能键入
printf("坐标被占用,请重新输入!\n");
else
{
board[x - 1][y - 1] = '*';
break;
}
}
else
printf("坐标非法,请重新输入!\n");//可能玩家会输入100 100,这当然也不行
}
}
void ComputerMove(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;
}
}
}
int IsFull(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 CheckWin(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 < row; 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[0][0] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
//平局
if (IsFull(board, row, col) == 1)//这里又调用IsFull函数
{
return 'E';
}
return 'C';
}
test.c
#include"game.h"
void menu()
{
printf("******** 三子棋 ********\n");
printf("1.开始游戏 2.退出游戏\n");
printf("**************************\n");
}
void game()
{
//数据的存储是二维数组
char board[ROW][COL];
//初始化棋盘-初始化为空格
InitBoard(board, ROW, COL);
PrintBoard(board, ROW, COL);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'C')
break;
PrintBoard(board, ROW, COL);
//电脑下棋
ComputerMove(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'C')
break;
PrintBoard(board, ROW, COL);
}
if (ret == '*')
printf("玩家赢!\n");
else if (ret == '#')
printf("电脑赢!\n");
else if (ret == 'E')
printf("平局\n");
}
int main()
{
int input = 2;
do { //这里用do...while循环
menu(); //菜单栏0
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game(); //三子棋游戏
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
system("cls");
} while (input-2); //直接用到真值判断是否继续游戏
return 0;
}
实现效果图
结束语
我们在编程学习中可以将一些简单的或者简化的游戏写出来,在为自己创造乐趣的同时也可以带来自身的进步,使coding不再乏味。也让自己在成长中体会别样的品味。