当前位置:网站首页>C语言简单实现三子棋小游戏
C语言简单实现三子棋小游戏
2022-08-03 05:11:00 【宗介@bit】
前言
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。今天用C语言简单实现这个小游戏。
一、大致思路
.1.三子棋的实现首先得有个简单的棋盘,其次要对棋盘上棋子数据进行存储处理,棋手对棋子应该进行合法有效的的操作。通过游戏规则对每场棋局进行合理的输赢判断。
2.通过上述的思考,可以简单梳理一下大致逻辑。
(1)棋盘的打印,初始化。
(2)棋子数据的存储。
(3)棋手对棋子的操作,以及对操作合法性的判断。
(4)输赢判断的简单逻辑。
二、具体功能的实现
1.构思
1.为了使得编写效率提高,逻辑功能设计思路更加清晰,该程序的实现采取模块化编程。首先建立3个文件:game.c(用来实现游戏各种逻辑业务功能),test.c(对游戏效果的简单测试),game.h(头文件的创建包含,各种功能函数的声明)。同时,为了简单的实现对数据的存储,我们通过数组来设计棋盘,用数组坐标来操作棋子,来实现棋子的移动。同时为了使得数组下标可以灵活点,用define 来定义数组下标。规定*
代表玩家的棋子,#
代表电脑的棋子。同时为了时电脑能够随机落子,利用rand函数和时间戳生成随机数。#define ROW 3 // 行 #define COL 3//列
2.功能函数的实现
1.游戏的入口 (游戏菜单的创建)
void menu()
{
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("*********************************\n");
}
简单的打印实现菜单,游戏的入口逻辑我们可以用do while循环简单实现,因为游戏得至少进去一次再考虑开始游戏和退出游戏,为了保证达到多次继续游戏得目的采用循环方式进入游戏。
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;
}
2.游戏的主体设计
1.棋盘的打印和初始化
设计初始化函数init_board将最开始的数据初始化为空格,这是为了最开始无子空棋盘的实现。接着设计棋盘打印函数 display_board
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 display_board(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)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
2.对棋子的操作
棋子的操作可以分为电脑操作和玩家操作两个函数来实现。对棋子的操作实现要满足两个条件.(1)棋子坐标是否合法.(2)该棋子坐标是否被占用。
可以通过数组定义的行列为条件来约束落子的下标,以及对数组坐标位置是否为空来进行判断该处是否被占用。
void player_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");
//0~32726
//%3-->0~2
while (1)
{
int x = rand() % row;//生成0~row内的随机数
int y = rand() % col;//生成0~col内的随机数
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
3.对棋局状态输赢的判断
游戏的状态有以下几种状态
1.玩家赢了 -返回"*"
2.电脑赢了 -返回"#"
3.平局 -返回"Q"
4.继续 -返回"C"
因为开始设计的时候玩家的棋子用*
表示,电脑的棋子用#
表示,所以为了减少谁赢的逻辑判断书写,直接返回值为棋盘的棋子所代表的字符。同时为了使得游戏在未结束的时候得以继续,因此增加了一个判断棋盘是否满了的函数,同时也可以判断棋局是否为平局。
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';
}
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.总结
1.源代码
(1)头文件
#pragma once
#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 display_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);
(2)game.c
#define _CRT_SECURE_NO_WARNINGS 1
#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 display_board(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)
{
//printf("---|---|---\n");
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)
{
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;//生成0~row内的随机数
int y = rand() % col;//生成0~col内的随机数
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//如果棋盘满了,返回1
//不满,返回0
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;
}
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';
}
(3)test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("*********************************\n");
}
void game()
{
char ret = 0;
//数据的存储需要一个3*3的二维数组
char board[ROW][COL] = {
0 };
init_board(board, ROW, COL);
display_board(board, ROW, COL);
//玩游戏
while (1)
{
player_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_move(board, ROW, COL);
display_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");
}
display_board(board, ROW, COL);
}
//玩家赢 - '*'
//电脑赢 - '#'
//平局了 - 'Q'
//游戏继续 - 'C'
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;
}
2.以上就是对3子棋简单的实现,如果有兴趣可以在此基础上改成五子棋、六子棋等等。以上内容如有错误,请多指教!
边栏推荐
猜你喜欢
Build your own web page on the Raspberry Pi (2)
13.
lt.647. Palindromic substring + lt.516. Longest palindrome subsequence 第四次培训
Kaggle 入门(Kaggle网站使用及项目复现)
Pr第二次培训笔记
Installation of Apache DolphinScheduler version 2.0.5 distributed cluster
13.< tag-动态规划和回文字串>lt.647. 回文子串 + lt.516.最长回文子序列
Ali cloud object storage oss private barrels to generate links
3. 无重复字符的最长子串
VSO Downloader Ultimate 5.0.1.45 中文多语免费版 在线视频下载工具
随机推荐
反射注解基础
三角形个数
2022暑假牛客多校联赛第一场
Installation of Apache DolphinScheduler version 2.0.5 distributed cluster
运行 npm run xxx 如何触发构建命令以及启动Node服务等功能?
Djiango第二次培训
Gradle的安装配置
判断回文数
Pr第四次培训笔记
2. 两数相加
传说中可“免费白拿”的无线路由器 - 斐讯 K2 最简单刷 breed 与第三方固件教程
1069 微博转发抽奖 (20 分)(C语言)
Redis6学习笔记
1230: 蜂巢
lintcode2330 · 计算x秒后的时间
Install IIS services (Internet Information Services (Internet Information Services, abbreviated IIS, Internet Information Services)
一劳永逸解决vs编译器无法使用scanf函数
详解Nurbs曲线
Makefile介绍
7.8(6)