首页 > 其他分享 >C语言——三子棋问题

C语言——三子棋问题

时间:2024-08-24 11:26:11浏览次数:11  
标签:int 三子 C语言 问题 col board row COL ROW

 三子棋可以拆分为三部分:

  1. test.c —— 测试游戏的逻辑。
  2. game.h —— 放置游戏相关的头文件、符号声明、函数声明。
  3. game.c —— 游戏相关的函数实现。

思路:

  1. 保证游戏可以一直玩下去 —— do...while循环
  2. 打印一个简易菜单 ——  函数 menu();
  3. 选择是否玩游戏 —— 输入选择
  4. 创建棋盘 —— 创建一个二维数组 —— 头文件中定义符号,便于修改棋盘大小
  5. 初始化棋盘 —— 初始化数组 —— 函数 Initboard()
  6. 打印棋盘 —— 函数 Displayed()
  7. 玩家下棋:(1) 输入坐标;(2) 判断坐标合法性;(3) 判断坐标是否被占用;(4) 判断输赢;(5)打印棋盘
  8. 电脑下棋:(1) 生成随机坐标;(2) 判断坐标是否被占用;(3) 判断输赢;(4)打印棋盘
  9. 判断输赢:(1) 玩家赢 — ‘*’;(2) 电脑赢 — ‘#’;(3) 平局 — Q;(4)游戏继续 — C

 //game.h 

//头文件的包含
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>



 //符号的定义
#define ROW 3
#define COL 3


 //函数声明

//棋盘初始化
void Initboard(char board[ROW][COL], int row, int col);

//打印棋盘
void Displayboard(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 is_win(char board[ROW][COL], int row, int col);
//1.玩家赢了 - *
//2.电脑赢了 - #
//3.平局 - Q
//4.游戏继续 - C
 //game.c

#include "game.h"

 //棋盘的初始化
void Initboard(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 Displayboard(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");          //以上是对第一行上半部分的打印,即图中的1
		if (i < row - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");           //以上是对第一行下半部分的打印,如图中的2
	}                           //i=1对应的是第一行的上下两部分合起来
		
}

 //玩家下棋
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)       //对于玩家来说,数组下标[0][0]即为[1][1]
		{
			//判断坐标是否被占用
			if (board[x - 1][y - 1] == ' ')        //减1后才对应数组的坐标
			{
				board[x-1][y-1] = '*';
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入:>\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入:>\n");
		}
	}
}

 //电脑下棋
void computermove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	while (1)
	{
		int x = rand() % row;          //模行得到行号    例:%3  余数0-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][1] != ' ')        //因为三者已经相等,只需要任意一个不等于空格即可
		{
			return board[i][1];   
		}
	}
	//判断三列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')        //因为三者已经相等,只需要任意一个不等于空格即可
		{
			return board[1][i];    
		}
	}
	//判断对角线
	if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '))
	{
		return board[1][1];
	}
	if ((board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' '))
	{
		return board[1][1];
	}
	//判断平局
	//如果棋盘满了返回1,不满返回0
	int ret = is_full(board, row, col);
	if (ret == 1)
	{
		return 'Q';
	}
	return 'C';
}
 //test.c

#include "game.h"

void menu()
{
	printf("**********************************\n");
	printf("*********     1. play      *******\n");
	printf("*********     0. exit      *******\n");
	printf("**********************************\n");
}

void game()
{
	//创建棋盘 - 二维数组
	char board[ROW][COL];     //头文件中可修改行、列的大小进而改变棋盘的大小

	//棋盘的初始化 - 数组的初始化
	Initboard(board, ROW, COL);

	//打印初始化后的棋盘 - 本质上是打印数组的内容
	Displayboard(board, ROW, COL);

	char ret = 0;
	while (1)
	{
		//玩家下棋
		playermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断玩家输赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
			break;

		//电脑下棋
		computermove(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断电脑输赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
			break;

	}
	if (ret == '*')
		printf("玩家胜利\n");
	else if (ret == '#')
		printf("电脑胜利\n");
	else
		printf("平局\n");
	Displayboard(board, ROW, COL);
}

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;
}

标签:int,三子,C语言,问题,col,board,row,COL,ROW
From: https://blog.csdn.net/2301_79914002/article/details/141476173

相关文章

  • C语言经典一百例分享
    c练习实例1题目:有 1、2、3、4 四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?程序分析:可填在百位、十位、个位的数字都是 1、2、3、4,组成所有的排列后再去掉不满足条件的排列。实例:以上实例输出结果为:c练习实例2题目:企业发放的奖金根据利润提成。利润......
  • WPF 的 await Application.Current.Dispatcher.InvokeAsync,Func 如果是Task , 等待赋
    最近在检查我们组内的代码,发现好多用到awaitApplication.Current.Dispatcher.InvokeAsync相信好多WPF的开发都会用到该方法做UI线程切换。但是细看里边的执行,发现了个别存在存在没有等待完成的情况  执行的结果是i为null值。这也就说明了执行了awaitApplica......
  • 如何解决接口数据重复问题?
    1.前端实现  前端设置按钮的状态,提交以后就加载,成功以后再恢复正常状态。  缺点:无法绝对保证不重复,但是前端实现可以减少网络请求2.后端通过幂等性来实现2.1幂等性概念  幂等指多次操作产生的影响只会跟一次执行的结果相同,通俗的说:某个行为重复的执行,最终获取......
  • 【漫谈C语言和嵌入式029】信号传输的对决:差分信号 vs. 单端信号的全面比较
            在现代电子电路和通信系统中,信号传输方式的选择对于系统性能、抗干扰能力和功耗等方面至关重要。其中,差分信号(DifferentialSignal)和单端信号(Single-EndedSignal)是两种常见的信号传输方式。它们各有优劣,适用于不同的应用场景。本文将深入探讨这两种信号传输方......
  • 【漫谈C语言和嵌入式028】稳压器的选择之道:线性稳压器与开关稳压器的深入比较
            在电子电路设计中,稳压器(Regulator)是不可或缺的组件,用于提供稳定的输出电压以满足电路的需求。稳压器的种类多种多样,其中最常见的两大类是线性稳压器(LinearRegulator)和开关稳压器(SwitchingRegulator)。它们在工作原理、效率、复杂性等方面各具特点,适用于不同的......
  • 【漫谈C语言和嵌入式027】探索信号处理的秘密:低通滤波器与高通滤波器的深度解析
            在嵌入式系统和数字信号处理领域,滤波器(Filter)是至关重要的工具。它们是用于处理和优化信号的基础组件,能够有效地控制信号的频率分布。滤波器的类型多种多样,其中最为基础且常用的便是低通滤波器(Low-PassFilter,LPF)和高通滤波器(High-PassFilter,HPF)。本文将......
  • 【快速上手C语言】第十七章:安全编程与最佳实践 - C语言中的风险防范与防御性编程
            在嵌入式系统和底层开发中,安全性是至关重要的。C语言由于其灵活性和高效性,广泛应用于系统级编程。然而,C语言也容易导致各种安全问题,如缓冲区溢出、整数溢出等。这些问题如果不加以重视,可能会带来严重的安全隐患。本文将探讨C语言中的常见安全问题,介绍安全编码......
  • 【CUDA编程笔记】thrust::device_vector<float> signal无法编译问题记录
    thrust::device_vectorsignal无法编译问题记录CUDA编程笔记一、问题记录正常编译时,无法编译二、源码#include<thrust/host_vector.h>#include<thrust/device_vector.h>#include<thrust/generate.h>#include<thrust/sort.h>#include<thrust/copy.h>#includ......
  • C语言中关于文件处理的常用函数
    目录标准IO流文本文件与二进制文件打开文件读写文件文本文件二进制文件文件定位关闭文件注意事项标准IO流在C语言中,流(Stream)是用于描述一切输入源或输出目的地的概念。流可以是键盘输入、屏幕输出,也可以是磁盘文件。标准流包括三个预定义的流:stdin:标准输入流,默......
  • 基于模拟退火算法求解物流选址问题(附word文档)
    基于模拟退火算法求解物流选址问题(附word文档)......