一、整个程序的实现思路及设计
实现思路
1.打印一个简单的菜单供玩家选择如下:
2.玩家下棋
3.电脑下棋
4.判断输赢
5.循环菜单是否要继续游戏
使用多文件的方式编写
- test.c文件游戏的框架
- game.c文件游戏的实现
- game.h文件游戏函数的声明
二、test.c文件的设计
在主函数(main)中的设计
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("三子棋\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请输入合理的选择\n");
break;
}
} while (input);
return 0;
}
使用menu()函数来打印菜单;
void menu()
{
printf("***********************************\n");
printf("************ 1.paly ********\n");
printf("************ 0.exit ********\n");
printf("***********************************\n");
}
使用do…while循环打印菜单;
使用srand()函数来随机生成电脑下的棋子;
使用switch根据玩家的选择来进行不同的实现;
游戏的实现放在game函数中;
void game()
{
//char board[3][3] = { 0 };
初始化棋盘
//InitBoard(board, 3, 3);
//定义一个数组用来存放数据
char board[ROW][COL] = {
0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
char ret = '0';
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret!='c')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != 'c')
{
break;
}
}
if (ret=='*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
整个test.c文件的代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("***********************************\n");
printf("************ 1.paly ********\n");
printf("************ 0.exit ********\n");
printf("***********************************\n");
}
void game()
{
//char board[3][3] = { 0 };
初始化棋盘
//InitBoard(board, 3, 3);
//定义一个数组用来存放数据
char board[ROW][COL] = {
0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
char ret = '0';
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret!='c')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DispalyBoard(board, ROW, COL);
ret=IsWin(board, ROW, COL);
if (ret != 'c')
{
break;
}
}
if (ret=='*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("三子棋\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请输入合理的选择\n");
break;
}
} while (input);
return 0;
}
三、game.h文件的设计
此文件主要用来声明函数如下:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//版本一没有使用对象宏来定义,以后修改更加的麻烦,
//void InitBoard(char board[3][3], int row, int col);
//初始化棋盘,放置空格
void InitBoard(char board[ROW][COL], int row, int col);
//声明打印棋盘的函数
void DispalyBoard(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 IsWin(char board[ROW][COL],int row,int col);
四、game.c文件的设计
1.使用InitBoard()函数初始化棋盘
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
2.使用DispalyBoard()函数打印棋盘
版本一:
void DispalyBoard(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++)
{
printf("%c", board[i][j]);
}
printf("\n");
}
}
版本二:
void DispalyBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//打印数据
printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);
printf("\n");
//打印分割行
if (i<row-1)
{
printf("---|---|---");
printf("\n");
}
}
}
版本三:
void DispalyBoard(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++)
{
printf(" %c ", board[i][j]);
if (j<col-1)
{
printf("|");
}
}
printf("\n");
//打印分割行 最后一行不答应所以需要判断
if (i < row - 1)
{
int j = 0;
for ( j = 0; j < col; j++)
{
printf("---");
//最后一个|不打印所以也需要判断
if (j<col-1)
{
printf("|");
}
}
printf("\n");
}
}
}
就以上三个版本来说:
我觉得最好的就是第三个版本,因为要是想改变棋盘的大小只需要在game.h中修改对象宏的大小即可,前两个版本都有一定的缺陷,我建议使用第三个版本来实现棋盘的打印,这样可以使代码的可读性和后期的修改更好。
3.使用PlayerMove()函数实现玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请输入坐标:\n");
while (1)
{
printf("玩家请输入,左边使用空格隔开:>");
scanf("%d %d", &x, &y);
//判断坐标的合法性
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");
}
}
}
以上的代码进行了两次判断:
- 第一次是判断坐标输入是否合法(也就是坐标是否在棋盘的范围)
- 第二次是判断坐标是否被占用,要是被占用就使用循环重新输入;
4.使用ComputerMove()函数实现电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
x = rand() % row;
y = rand() % col;
printf("电脑下棋\n");
while (1)
{
if (board[x][y]==' ')
{
board[x][y] = '#';
break;
}
}
}
其中使用了rand()函数它的作用是生成随机的值
- 使用rand()%row是来控制随机值的大小
- 同时还要再主函数中使用srand()函数来声明
- 再game.h头文件中还要引用两个头文件(stdlib.h和time.h)
5.使用IsWin()函数实现结果的判断
版本一:
char IsWin(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[0][0]!=' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局
if (IsFull(board,row,col)==1)
{
return 'Q';
}
//继续
return 'c';
}
版本二:
char IsWin(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] != ' ') {
//如果列上连续的三个值相等就返回,注意j+2不能超过列
if (j < col - 2 && board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2]) {
return board[i][j];
}
//如果行上连续的三个值相等就返回,注意i+2不能超过行
else if (i < col - 2 && board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j]) {
return board[i][j];
}
//如果左斜线上连续的三个值相等就返回
else if (i < row - 2 && j < col - 2 && board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2]) {
return board[i][j];
}
//如果右斜线上连续的三个值相等就返回
else if (i >= 2 && j <= i && board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j +2]) {
return board[i][j];
}
}
}
}
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'c';
}
以上的两个版本我更加喜欢第二个版本:
- 当棋盘的大小改变的时候,也可以进行判断不需要再次修改代码
- 版本一只适合3*3的棋盘
综上考虑个人觉得第二个版本更加的好
6.使用IsFull()函数判断棋盘是否下满
int IsFull(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;
}
下面是game.c完整的代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
//版本1
//void DispalyBoard(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++)
// {
// printf("%c", board[i][j]);
// }
// printf("\n");
// }
//}
//版本二
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// for (i = 0; i < row; i++)
// {
// 打印数据
// printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);
// printf("\n");
// 打印分割行
// if (i<row-1)
// {
// printf("---|---|---");
// printf("\n");
// }
//
// }
//}
//版本三
void DispalyBoard(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++)
{
printf(" %c ", board[i][j]);
if (j<col-1)
{
printf("|");
}
}
printf("\n");
//打印分割行 最后一行不答应所以需要判断
if (i < row - 1)
{
int j = 0;
for ( j = 0; j < col; j++)
{
printf("---");
//最后一个|不打印所以也需要判断
if (j<col-1)
{
printf("|");
}
}
printf("\n");
}
}
}
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请输入坐标:\n");
while (1)
{
printf("玩家请输入,左边使用空格隔开:>");
scanf("%d %d", &x, &y);
//判断坐标的合法性
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 ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
x = rand() % row;
y = rand() % col;
printf("电脑下棋\n");
while (1)
{
if (board[x][y]==' ')
{
board[x][y] = '#';
break;
}
}
}
//判断棋盘是否下满
int IsFull(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;
}
//判断结果的第二个版本
char IsWin(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] != ' ') {
//如果列上连续的三个值相等就返回,注意j+2不能超过列
if (j < col - 2 && board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2]) {
return board[i][j];
}
//如果行上连续的三个值相等就返回,注意i+2不能超过行
else if (i < col - 2 && board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j]) {
return board[i][j];
}
//如果左斜线上连续的三个值相等就返回
else if (i < row - 2 && j < col - 2 && board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2]) {
return board[i][j];
}
//如果右斜线上连续的三个值相等就返回
else if (i >= 2 && j <= i && board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j +2]) {
return board[i][j];
}
}
}
}
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'c';
}
以上就是我关于使用C语言怎么自定义棋盘大小来实现三子棋的代码,希望能帮到大家,更好的掌握这门语言,请大家给我多评论,让我知道自己的不足,从而大家共同进步。谢谢大家的点赞!!!!!!!!!!!
今天的文章c语言三子棋程序_将文本效果设置为棋盘下教程分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88438.html