【C语言实战】小伙子,你真的掌握数组了吗?--- 三子棋

news2024/12/26 3:14:20

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:课设
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨


目录

  • 一、思想及准备工作
  • 二、游戏菜单(test.c)
  • 三、选择逻辑补充(test.c)
  • 四、游戏接口(test.c)
  • 五、游戏实现
      • 5.1 实现内容(Trimoku.h)
      • 5.2 初始化棋盘(Trimoku.c)
      • 5.3 打印棋盘(Trimoku.c)
      • 5.4 玩家下棋(Trimoku.c)
      • 5.5 电脑下棋(Trimoku.c)
      • 5.6 判断输赢(Trimoku.c)
  • 六、源代码
      • 6.1 test.c
      • 6.2 Trimoku.h
      • 6.3 Trimoku.c

一、思想及准备工作

  1. 实现一个简易菜单供玩家选择是否要玩游戏
  2. 初始化棋盘和打印棋盘(二维数组)
  3. 玩家代表*先下棋并打印棋盘,接着电脑代表#再下棋并打印棋盘
  4. 判断游戏输赢。游戏可能存在玩家赢、电脑赢和平局

最后为了方便管理,我们可以创建多个文件来实现

  • test.cpp — 测试代码逻辑 (源文件)
  • Trimoku.c — 逻辑实现 (源文件)
  • Trimoku.h — 存放函数的声明 (头文件)

二、游戏菜单(test.c)

为了可以让游戏反复玩,则需要菜单来提醒玩家是否继续或退出,那么该如何实现菜单呢?让我们看看下面的代码

#include "Trimoku.h"
void menu()
{
	printf("*****************************\n");
	printf("********   1. play     ******\n");
	printf("********   0. eixt     ******\n");
	printf("*****************************\n");
}

int main()
{
	int input = 0;
	do
	{
		// 封装函数打印菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		
	} while ();
		
	return 0;
}

代码详解:想反复玩游戏,肯定需要循环,这里我们采用do while循环。接下来封装一个函数menu(菜单的意思)

三、选择逻辑补充(test.c)

int main()
{
	int input = 0;
	do
	{
		// 封装函数打印菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("游戏开始\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

这里可以输入任何值,假设规定输入1开始游戏,输入0则退出游戏,但万一玩家不小心输入其他值时,我们是不是要提醒玩家输入错误,重新选择,这时switch语句就派上用场了。最后循环条件是input,大家想想,假如input0,判断为假,则结束循环,这不就和退出游戏相互匹配上了。(0为假,非0为真)

【程序效果】

在这里插入图片描述

四、游戏接口(test.c)

void game()
{
	// 1. 棋盘(3 × 3)
	char board[ROW][COL];
	// 初始化棋盘为全空格
	init_board(board, ROW, COL);
	//打印棋盘
	print_board(board, ROW, COL);
}

可以定义一个3 × 3的二维数组,然后封装一个函数init_board将数组的元素初始化成空格。最后再封装一个打印函数print_board来打印一个简易的棋盘如下:
在这里插入图片描述

接下来就是电脑和玩家下棋的逻辑:

void game()
{
	// 1. 棋盘(3 × 3)
	char board[ROW][COL];
	// 初始化棋盘为全空格
	init_board(board, ROW, COL);
	//打印棋盘
	print_board(board, ROW, COL);
	// 下棋
	while (1)
	{
		// 2. 玩家下棋(*)
		player_move(board, ROW, COL);
		print_board(board, ROW, COL);
		
		// 3. 电脑下棋(#)
		computer_move(board, ROW, COL);
		print_board(board, ROW, COL);
	}
	if (ret == '#')
		printf("电脑赢了\n");
	else if (ret == '*')
		printf("玩家赢了\n");
	else if (ret == 'Q')
		printf("平局\n");
}

玩家下完棋就到电脑下,电脑下下完棋后又轮到玩家下棋,直到一方胜利结束,因此是一个循环。那循环什么时候 结束呢?不就是当一方赢得比赛或平局就结束了。因此,接下来是判断游戏输赢:

void game()
{
	// 1. 棋盘(3 × 3)
	char board[ROW][COL];
	char ret = 0;
	// 初始化棋盘为全空格
	init_board(board, ROW, COL);
	//打印棋盘
	print_board(board, ROW, COL);
	// 玩家下完棋就到电脑下,直到一方胜利结束,因此是一个循环
	while (1)
	{
		// 2. 玩家下棋(*)
		player_move(board, ROW, COL);
		print_board(board, ROW, COL);
		// 4. 判断输赢(玩家)
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		// 3. 电脑下棋(#)
		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");
}

五、游戏实现

5.1 实现内容(Trimoku.h)

#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);

这里说说为什么要用#define来定义棋盘的大小。原因是:假设需要一个5 × 5的棋盘,如果没有宏定义,就要将代码中所有二维数组的大小改一遍,这样比较浪费时间。

5.2 初始化棋盘(Trimoku.c)

void init_board(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

将二维数组的元素全部初始化为空格

5.3 打印棋盘(Trimoku.c)

void print_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");
		}
	}
}

在这里插入图片描述为了保持棋盘美观,注意右边界和下边界不需要再打印|___

5.4 玩家下棋(Trimoku.c)

void player_move(char board[ROW][COL], int row, int col)
{
	// 提示玩家可以落子
	printf("玩家下棋\n");
	while (1)
	{
		printf("请输入要下棋的坐标:>");
		int x = 0;
		int y = 0;
		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");
		}
	}
}

注意:玩家并不知道数组是从0开始的;并且还要判断坐标的合法性,不能在已经下过棋的坐标再下棋。

5.5 电脑下棋(Trimoku.c)

void computer_move(char board[ROW][COL], int row, int col)
{
	// 提示电脑下棋
	printf("电脑下棋:\n");
	while (1)
	{
		// 电脑随机往空的坐标下棋
		// 三子棋横坐标是0~2
		int x = rand() % row;//rand的范围是0~32767,%row,范围就是0~2
		int y = rand() % col;// 纵坐标同理
		// 同时还要判断坐标是否被占用
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

电脑下棋就比较简单了,电脑只需要随机往空的坐标下棋,因此可以使用到rand函数,在猜数字游戏就讲过,调用rand函数前应该先使用srand,而srand只能被调用一个,因此可以放到主函数中。最后也得判断坐标是否被占用。

5.6 判断输赢(Trimoku.c)

//我希望is_full这个函数只是为了支持is_win函数的,只是在is_win函数内部使用
//那我们就没必要在头文件中声明,因此可以用static修饰函数

//判断棋盘是否满了
static 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)
{
	//判断三行
	for (int 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 (int 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];
	}

	// 可能存在平局(棋盘满了情况),满了返回1
	if (is_full(board, row, col) == 1)
	{
		return 'Q';
	}

	// 以上的情况都不存在,游戏继续
	return 'C';
}

对于三子棋来说,只要某一行、某一列或者是对角线是相同的元素,就代表某一方游戏胜利;但游戏也会存在平局,对于平局的情况,只需要知道棋盘是否都占满了元素;最后,如果棋盘还有空位可以下棋,代表游戏继续。

六、源代码

6.1 test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Trimoku.h"

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

void game()
{
	// 1. 棋盘(3 × 3)
	char board[ROW][COL];
	char ret = 0;
	// 初始化棋盘为全空格
	init_board(board, ROW, COL);
	//打印棋盘
	print_board(board, ROW, COL);
	// 玩家下完棋就到电脑下,直到一方胜利结束,因此是一个循环
	while (1)
	{
		// 2. 玩家下棋(*)
		player_move(board, ROW, COL);
		print_board(board, ROW, COL);
		// 4. 判断输赢(玩家)
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		// 3. 电脑下棋(#)
		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");
	// 判断输赢要告诉我们电脑赢(返回#)or玩家赢(返回*)or平局(返回q)or游戏继续(c)
}

//判断输赢
//判断输赢的代码要告诉我:电脑赢了?玩家赢了?玩家赢?游戏继续?
//电脑赢:#
//玩家赢:*
//平局:Q
//游戏继续:C

void test()
{
	// 因为time的返回值是time_t,而srand又需要unsigned int
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		// 封装函数打印菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

6.2 Trimoku.h

#pragma once

#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);

6.3 Trimoku.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Trimoku.h"
void init_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++)
		{
			board[i][j] = ' ';
		}
	}
}

void print_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");
		}
	}
}

void player_move(char board[ROW][COL], int row, int col)
{
	// 提示玩家可以落子
	printf("玩家下棋\n");
	while (1)
	{
		printf("请输入要下棋的坐标:>");
		int x = 0;
		int y = 0;
		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 computer_move(char board[ROW][COL], int row, int col)
{
	// 提示电脑下棋
	printf("电脑下棋:\n");
	while (1)
	{
		// 电脑随机往空的坐标下棋
		// 三子棋横坐标是0~2
		int x = rand() % row;//rand的范围是0~32767,%row,范围就是0~2
		int y = rand() % col;// 纵坐标同理
		// 在猜数字就讲过,调用rand函数前应该先使用srand,而srand只能被调用一个,因此可以放到主函数
		// 同时还要判断坐标是否被占用
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//我希望is_full这个函数只是为了支持is_win函数的,只是在is_win函数内部使用
//那我们就没必要在头文件中声明
// 
//判断棋盘是否满了
static 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];
	}

	// 可能存在平局(棋盘满了情况),满了返回1
	if (is_full(board, row, col) == 1)
	{
		return 'Q';
	}

	// 以上的情况都不存在,游戏继续
	return 'C';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/745792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第一百零五天学习记录:数据结构与算法基础:顺序表(王卓教学视频)

注&#xff1a;笔记截图均来自王卓数据结构教学视频 线性表的定义和特点 线性表是具有相同特性的数据元素的一个有限序列 同一线性表中的元素必定具有相同特性&#xff0c;数据元素间的关系是线性关系。 线性表的逻辑特征 稀疏多项式的运算 顺序存储结构存在的问题 1、存…

eNSP-MSTP多实例生成树

MSTP多实例生成树 文章目录 MSTP多实例生成树一、拓扑结构二、基本配置三、测试验证四、知识点详解 一、拓扑结构 二、基本配置 SW1: #创建vlan <Huawei>sys [Huawei]sys sw1 [sw1]un in en [sw1]vlan batch 2 to 20 #将接口划入vlan [sw1]port-group group-member Gig…

linux常用的命令

一.操作目录命令 1.1 ls 命令 语法&#xff1a; ls [选项] [目录或文件] 功能: 对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含…

MQTT emqx.conf

MQTT download_spencer_tseng的博客-CSDN博客 MQTT emqx-5.1.1-windows-amd64_spencer_tseng的博客-CSDN博客 c:/emqx-5.1.1-el8-amd64/etc/emqx.conf

第 108 场LeetCode双周赛

A 最长交替子序列 暴力枚举 class Solution { public:int alternatingSubarray(vector<int> &nums) {int n nums.size();for (int len n; len > 1; len--) {for (int i 0; i len - 1 < n; i) {int j i 1;for (; j < i len; j)if (nums[j] - nums[j …

mysql一条更新语句是如何被执行的——带你了解mysql更新语句执行内部顺序

文章目录 写在前面一、缓冲池 Buffer Poll二、Redo log1、磁盘寻址的过程2、redo log特点 三、Undo log四、更新过程五、InnoDB总体架构1、内存结构&#xff08;1&#xff09;Buffer Pool&#xff08;2&#xff09;预读机制&#xff08;3&#xff09;LRU算法&#xff08;4&…

安装Ceph集群

安装Ceph集群 环境准备 CentOS 7.6 主机名IPRoleadmin192.168.182.128adminnode1192.168.182.129mon/mgr/osdnode2192.168.182.130osdnode3192.168.182.131osdclient192.168.182.132 所有节点修改主机名相互解析三台node节点添加大小5G以上硬盘关闭所有节点防火墙与SeLinux所…

机器学习 day25(softmax在神经网络模型上的应用,提高数据精度的方法)

输出层采用softmax 在识别手写数字的模型中&#xff0c;预测y只有两个结果&#xff0c;所以输出层采用sigmoid激活函数且只有一个神经元。若预测y有10个结果&#xff08;0-9&#xff09;&#xff0c;该模型的前向传播计算方式与识别数字的模型完全相同&#xff0c;即隐藏层的…

【力扣算法07】之 2.两数相加 python

文章目录 问题描述示例1示例2示例 3提示 思路分析代码分析完整代码详细分析 完结 问题描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同…

RabbitMQ常用工作模式+整合springboot

目录 1.MQ的相关概念 1.1 什么是MQ消息中间件 1.2 为什么使用MQ (1) 应用解耦 (2) 异步提速 (3)削峰填谷 1.3 使用MQ的劣势 1.4 常见的MQ组件​​​​​​​ 2. RabbitMQ的概述 2.1 RabbitMQ的概念 2.2 RabbitMQ的原理 2.3 安装RabbitMQ 3. RabbitMQ 的工作模式…

Swift与OC的混编

一些场面话 在一位前辈的博客里看到了关于iOS开发的各种语言的混编&#xff0c;浅浅学习一下怎么使用。不得不说语言混编的开发者是真的&#x1f42e;&#x1f37a; Swift中用OC混编 新建一个Swift文件 创建一个OC的类 选择language为OC 继续往下走&#xff0c;会跳出这个界…

学无止境·MySQL⑤(存储函数、存储过程)

存储函数和存储过程试题 试题一1、创建一个可以统计表格内记录条数的存储函数 &#xff0c;函数名为count_sch()2、创建一个存储过程avg_sai&#xff0c;有3个参数&#xff0c;分别是deptno&#xff0c;job&#xff0c;接收平均工资&#xff0c;功能查询emp表dept为30&#xff…

C/C++用socket实现简单的TCP文件传输

C/C:用socket实现简单的TCP文件传输 网络中进程之间如何进行通信socket是什么socket的基本操作socket()函数bind()函数listen()、connect()函数accept()函数recv()/send()函数close()函数 TCP的“三次握手”“三次握手”的作用 TCP的“四次挥手”四次挥手的一些注意事项 代码实…

【附3.7安装包】python安装包下载及安装(超详细)

python3.7链接&#xff1a;https://pan.baidu.com/s/1Ett3XBMjWhkVOxkOU8NRqw?pwdqz3l 提取码&#xff1a;qz3l 今日资源&#xff1a;Python 适用系统&#xff1a;WINDOWS ​ Python 3.7.0 软件介绍&#xff1a; Python是一款通用型的计算机程序设计语言&#xff0c;Pytho…

【Leetcode】19. 删除链表的倒数第N个节点

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#xff1f; 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&…

有没有线上兼职的副业,在家可以做什么赚钱

线上兼职副业啊&#xff0c;确实是一个不错的副业选择&#xff01;不过&#xff0c;我得提醒你&#xff0c;如果想要那种点一下鼠标就会下金币的神仙项目&#xff0c;这样的期待的话&#xff0c;那我只能告诉你&#xff0c;你可能走错地方了&#xff0c;在这帮不了你。 在线上赚…

LeetCode[470]用Rand7()实现Rand10()

难度&#xff1a;Medium 题目&#xff1a; 给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数&#xff0c;试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。 你只能调用 rand7() 且不能调用其他方法。请不要使用系统的 Math.random() 方法。 每个测试用例将有一个内部…

Python案例分析|基于模块的库存管理系统

本案例是通过一个多模块的库存管理系统案例&#xff0c;帮助大家深入了解基于模块的Python应用程序的开发流程。 01、库存管理系统API设计 本文实现一个简单的基于模块的库存管理系统。系统采用JSON文件来保存数据。产品信息设计为字典&#xff0c;键为sku_id&#xff08;产品…

软件工程——第13章软件项目管理知识点整理(完结)

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.管理的定义&#xff1f; 2.软件项目管理地位&#xff1f;&#xff08;重要性&#xff09; 3.软件项目管理过程从一组项目计划活动开始&#xff0c…

怎么制作查询成绩的网页?这个不用代码的方法你用过没?

作为一名老师&#xff0c;与家长沟通交流是日常工作中重要的一部分。特别是每次考完试后&#xff0c;家长都急切地想了解孩子的成绩&#xff0c;以便能及时了解孩子的学习情况并给予适当的支持和指导。然而&#xff0c;为了保护学生的隐私&#xff0c;大部分学校不公开张榜学生…