【源码+文档+调试讲解】基于Java的推箱子游戏设计与实现

news2024/11/24 18:42:31

摘    要

社会在进步,人们生活质量也在日益提高。高强度的压力也接踵而来。社会中急需出现新的有效方式来缓解人们的压力。此次设计符合了社会需求,Java推箱子游戏可以让人们在闲暇之余,体验游戏的乐趣。具有操作简单,易于上手的特点。

推箱子游戏的玩法十分简单——控制人物绕过障碍物,到达目的地。此次毕业设计基于Java语言。将游戏地图做成通用的关卡设计,关卡用二维数组实现,在二维数组中设置值域来表示不同对象,运用二维数组的遍历算法来加载对应图片实现了游戏图片初始化状态。同时,通过初始化多个不同二维数组实现了游戏地图关卡的设计,方法巧妙且简单易行,有效的解决了图片排布问题。充分运用类和方法的调用来实现游戏关卡的初始化。用读取键值的方法判断游戏人物移动、停止、到达目的地。舒缓的音乐配合有趣的步骤,相信能引起很多人的兴趣。作为一个具有悠久历史的游戏,也能够引起人的怀念和共鸣。

关键词  Java 游戏 二维数组 算法 读取键值 栈

Sokoban based on Java

Abstract

Social progress, quality of life is also increasing. High-intensity pressure also follows. The emergence of new social urgently needed an effective way to relieve people's stress. This is designed to meet the needs of the community, Java Sokoban game allows people in her spare time, experience the fun of the game. With simple operation, easy to use features. 

Sokoban game’s rule is very simple - control characters around obstructions, to arrive at the destination. The graduation project is based on Java language. Game map to make a generic level design, level with two-dimensional array implementation, set the domain in a two-dimensional array to represent different objects, using the two-dimensional array of times calendar calculation method is realized to load the corresponding picture game image initialized state. At the same time, through the initialization of several different two-dimensional arrays realized the design of the game map level, a method is clever and simple, easy to effectively solve the problem of the picture arrangement. Make full use of calling classes and methods to implement the initialization of the game levels with reading the key value method to judge the characters move, stop, or reaching its destination. Soothing music with interesting step, which will hopefully lead to a lot of people's interest. As a game with a long history, but also can cause people to miss and resonance.

Key Words: Java game; two-dimensional arrays; algorithm; key value method; stack;

目    录

摘    要 i

Abstract ii

引    言

1  系统分析

1.1  技术可行性分析

1.1.1  可行性目的

1.1.2  可行性研究前提

1.1.3  算法可行性分析

1.1.4  平台选择

1.2  需求分析

1.2.1  引言

1.2.2  游戏需求

1.2.3  软硬件需求

1.2.4  接口控制

1.3  方案论证

1.3.1  C++语言的优点

1.3.2  Java语言的优点

1.3.3  C语言的优点

1.3.4  方案选择

2  概要设计

2.1  游戏设计分析

2.1.1  地图文件的引用

2.1.2  程序运逻辑

2.1.3  绘图

2.1.4  显示平台

2.2  注意事项

2.3  游戏流程图

2.4  函数模型

3  详细设计

3.1  游戏总体结构与代码

3.2  选关模块

3.3  地图的绘制形成

3.4  小人与箱子移动的算法

3.5  小人上下移动模块

3.6  悔棋模块

3.7  音乐控制

4  游戏测试

4.1  软件测试

4.1.1  软件测试简介

4.2 测试方法

4.3 测试步骤

4.4  游戏系统性能分析

5  项目经验与总结

6  参考文献

7  致谢

8  外文原文及中文翻译

引    言

策略性游戏可以锻炼人的思维能力还能缓解人的压力,使人们暂时忘却生活当中的烦恼,增强人们的逻辑思维能力,游戏的艺术美也吸引着越来越多的玩家和厂商,寓教于乐,在放松人们心情的同时还可以活跃双手。在人类的社会生活当中,游戏占有很大的比重,并且随着社会的发展而不断发展。而且游戏本身具有激发人类潜在行为的特质,是一种能够吸引人们参与其中的活动,其本身具有强烈的吸引力使游戏者卷入其中;再者适当的游戏、合理的时间安排,能够让玩家在娱乐的同时还可以锻炼其反应速度及灵敏程度,亦可让玩家从压力中释放出来。因此游戏逐渐成为人们生活中不可缺少的一部分,游戏产业也正逐步发展成熟。

经典的推箱子游戏是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。它的玩法也非常简单,在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,控制人物不停的移动将箱子推到目的位置才能顺利的完成任务。难点在于移动的位置,以及箱子到达指定位置的顺序,只有多加思考才能获得游戏的胜利。反复推敲,锻炼了人们的耐性。本次的开发尽量多的设置了关卡数目,增强游戏的耐玩性,同时在画面上有所提高,借鉴了许多达人的经验和技术,引发了我对游戏的热爱,丰富了个人生活,相信推箱子游戏在今后的社会总会越来越引人注目。

1  系统分析

1.1  技术可行性分析

1.1.1  可行性目的

通过推箱子游戏中使用的Java技术,让我能够更加熟练的使用Eclipse。同时了解相关运行环境的配置。将理论知识和实际操作结合起来。达到学以致用的目的。网上资料的查询极大的提高了我的自学能力。希望经过此次设计,锻炼自己的思考,解决问题的能力。对系统开发的流程有更深层次的理解,检验学习成果和实际动手能力,对底层知识有更深的了解。为今后的工作打好基础。

1.1.2  可行性研究前提

基本需求:通过规范的开发流程,采用面向对象的分析设计方法实现游戏美观,易玩,及时等特性。操作性方面主要通过键盘的借口实现,操作键位是上下左右。

主要开发目标:通过此次研究熟练Java的相关知识和技术的应用,界面美化的工作需要同学的帮助,了解团队和合作的重要,熟悉不同领域相关技术的交叉,完成Java推箱子游戏的基本功能。

条件假定和限制:Java相关技术的使用不是很熟练,如果有些游戏bug没有及时发现,相关升级版本需要之后弥补,更正。

可行性研究所采用的方法和步骤,通过研究分析推箱子小游戏所需要的功能以及实现的方法、确定主体结构。利用所学到的知识,以最简洁、最容易的办法,边开发边测试边修改,实现一个初级游戏软件。

评价尺度,实现基础的推箱子功能,如输赢判定,人物的移动位置,箱子的移动位置,同时加强画面的优化,音乐的选定等基础功能。更强的优化需要以后的升级和修改,实现相关功能就达到目标。

1.1.3  算法可行性分析

管理可行性:

此次设计基于Java,有面向对象,可移植性,安全性,并发机制,支持可视化图形界面等特点。易于管理。

经济可行性: 

经济可行性是指可以使用的资源的可能性(资源包括人力资源、自然资源和资金条件)。

经济可行性的内容

经济可行性包括两个方面的内容:一是某一备选方案占有和使用经济资源的可能性,进而实现政策目标的可能性;二是实施某一政策方案所需花费的成本和取得的收益。政府的财政资源是有限的,任何政策方案占有和使用的经济资源也是有限的。因此,任何一项公共政策都存在一个争取公共经济资源的问题。一般说来,“公共政策的经济资源的占有量与其政策目标的期望值成正比例关系。”当然,这还涉及到一个成本效益问题。如果某一方案的成本大于收益,显然这项政策是不可行的。

经济可行性的方法

评估经济可行性有两个基本方法:成本-效益分析或损益分析,成本-效能分析(或称成本-有效性分析)。

经济可行性的标准

经济可行性的具体标准有投入产出比(O/I)、效率(efficiency)、效力(effectiveness)、利润率(profitability)等。这里主要特别说明效率和效力这两个概念。效率是以最小的投入取得最大的产出;效力则是以最小的成本实现即定的目标。二者虽然相关,但却不能混淆,最高效率和最高效力不一定出现在同一个点上。举一个简单的例子,你购买一本书的最小成本是20元,但当你同时买10本同样的书时,只需180元。这后一种显然更有效力(一本书的成本只要18元),但问题是同样的书你只要一本就够了,显然这后一种就不能满足你最基本的目标了。

本次设计注重游戏功能的实现,达到设计目的,不用于其他的商业用途。通过此次设计增强Java技术和实践的结合。同时了解可视化界面,设计操作界面和页面的跳转更换。操作环境需要Eclipse。相关资料可以上网查询。硬件方面可以普通笔记本可以达到要求。

技术可行性:

对于本游戏,可以使用如VB,Java,Delphi等相关的编程语言,但是考虑到编写程序的难易程度以及对编译语言的了解程度,本游戏选择Java程序语言作为编程语言。需要对变量定义、变量初始化、界面初始化、游戏初始化等,然后就可以进入游戏,处理游戏过程中的各种操作。同时进行技术可行性分析时,要注意以下一些问题。 

1.全面考虑系统开发过程所涉及的所有技术问题

软件开发涉及多方面的技术,包括开发方法、软硬件平台、网络结构、系统布局和结构、输入输出技术、系统相关技术等。应该全面和客观地分析软件开发所涉及的技术,以及这些技术的成熟度和现实性。

2.尽可能采用成熟技术

成熟技术是被多人采用并被反复证明行之有效的技术,因此采用成熟技术一般具有较高的成功率。另外,成熟技术经过长时间、大范围使用、补充和优化,其精细程度、优化程度、可操作性、经济性等方面要比新技术好。鉴于以上原因,软件项目开发过程中,在可以满足系统开发需要、能够适应系统发展、保证开发成本的条件下,应该尽量采用成熟技术。

3.慎重引入先进技术

在软件项目开发过程中,有时为了解决系统的特定问题,为了使所开发系统具有更好的适应性,需要采用某些先进或前沿技术。在选用先进技术时,需要全面分析所选技术的成熟程度。有许多报道的先进技术或科研成果实际上仍处在实验室阶段,其实用性和适应性并没有得到完全解决,也没有经过大量实践验证,在选择这种技术时必须慎重。例如,许多文章中已经报道了指纹识别技术,而且市场上也有实验性产品,但指纹识别技术至今仍有许多重大技术难题没有突破,离具体应用仍有一定距离。因此,在项目开发中要谨慎选用这种技术。如果不加分析,在项目中盲目采用指纹识别技术,应用时肯定会出现许多难以解决的具体问题。

4.着眼于具体的开发环境和开发人员

许多技术总的来说可能是成熟和可行的,但是在开发队伍中如果没有人掌握这种技术,而且在项目组中又没有引进掌握这种技术的人员,那么这种技术对本系统的开发仍然是不可行的。例如,分布对象技术是分布式系统的一种通用技术,但是如果在开发队伍中没有人掌握这种技术,那么从技术可行性来看就是不可行的。

5.技术可行性评价

技术可行性评价是通过原有系统和欲开发系统的系统流程图和数据流图,对系统进行比较,分析新系统具有的优越性,以及对设备、现有软件、用户、系统运行、开发环境、运行环境和经费支出的影响,然后评价新系统的技术可行性。

社会可行性:

社会可行性是在特定环境下对项目的开发与实施。
  社会就是由许多个体汇集而成的有组织有规则或纪律的相互合作的生存关系的群体。没有分工与合作关系的个体所聚集成的群体不成为社会。本次设计基于学习的需要,所做毕业设计的内容不会在社会上进行商业运作。网上所查的资料以及相关的知识的引用,属于学术交流,不涉及版权,以及法律责任。同时不会对社会产生负面的影响,不存在不可行性。

算法实现:以人为中心,出现两种可能:①人在空位 ②人在目标位置上

  • 有六种可能:(注:x1,y1, x2, y2为坐标的偏移量,i ,为人所在的坐标 )

②人在目标位置上 同样也有六种可能:

对于工人的操作很简单:4个方向的移动,工人移动箱子也随之移动。

地图数据最为关键:第一关的地图都要更换,这些位置也要变,首先我们设计一个二维数组map.我们所地图想象成一个网格,每个格子就是图片的大小30像素,工人和箱子每步移动的距离也是30像素

假设工人移动方式向右,其它方向原理是一致的,P1、P2分别代表工人移动趋势方向前的两个方格

(1)前方P1是围墙:

如果工人前方是围墙 {

退出规则判断,布局不做任何改变

}

(2)前方P1是通道或目的地

如果工人前方是通道或目的地 {

工人可以进入到P1方格,修改相关位置的格子状态值

}

(3)前方P1是箱子

在这种情况,需要判断箱子(P1)前方P2处的物体,来判断工人是否可以移动,此时有以下可能:

一、P1处为箱子(BOX)或者放到目的地的箱子,P2处为通道:工人可以进到P1方格,P2方格的状态可以修改为箱子,修改相关格子的状态值

二、P1处为箱子或者放到目的地的箱子,P2处为目的地:工人可以进到P1方格,P2处为放到目的地的箱子,修改相关格子的状态值

三、P1处为箱子,P2处为墙:退出判断规则布局不做任何改变

1.1.4  平台选择

Eclipse是一个开放源代码的软件开发项目,专注于为高度集成的工具开发提供一个全功能的、具有商业品质的工业平台。它主要由Eclipse项目Eclipse工具项目Eclipse技术项目三个项目组成,具体包括四个部分组成——Eclipse Platform、JDT、CDT和PDE。JDT支持Java开发、CDT支持C开发、PDE用来支持插件开发,Eclipse Platform则是一个开放的可扩展IDE,提供了一个通用的开发平台。它提供建造块和构造并运行集成软件开发工具的基础。

分析对象的技巧在于它的重复利用及维护效率。如果要把设计出来的程序在不同的显示平台上执行,就要作大幅度的更动甚至重写,这样就失去了面向对象属性,所以在本程序分析时将不变与易变的因素分别做成对象,如地图文件、小人与箱子的移动以及程序的运算逻辑就是不变的项目,而绘图及显示平台会因为环境而有所不同属于易变的项目。

虽然大多数用户很乐于将 Eclipse 当作 Java集成开发环境(IDE)来使用,但 Eclipse 的目标却不仅限于此。Eclipse 还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展 Eclipse 的软件开发人员,因为它允许他们构建与 Eclipse 环境无缝集成的工具。由于 Eclipse 中的每样东西都是插件,对于给 Eclipse 提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。

1.2  需求分析

1.2.1  引言

随着计算机在日常工作中的普及,软件开发行业作为其必不可少的组成部分,被人们所认可。在我国,软件行业日渐成熟,小作坊式的开发形式,已经不能满足我国对于软件规范化、实用性的要求,软件开发流程化及各个职能部门工作的有效划分和正确协作,是现在软件行业面临的一个较大的问题。软件需求分析是软件开发的出发点,为设计起到指导性作用,所以需求分析在软件行业及开发流程中起着非常重要的作用。 

“需求分析”,就是对需要解决的问题进行详细分析,弄清楚需要解决的问题。开发人员需要了解顾客的需求,然后体现在软件中。如果说软件开发过程中,开发人员需要了解自己做什么,顾客需要告诉开发人员自己需要什么,而需求分析就是连接开发人员和顾客之间的重要纽带。只有真正理解顾客的需求,才能设计出顾客所需要的软件。

在过去很长一段时间,开发人员的认为需求分析是整个开发过程中最简单的一个环节。然后越来越多的开发人员认识到它才是整个开发过程中的核心部分。正所谓“磨刀不误砍柴工”。只有真正理解了顾客的需求,才能顺利开发出顾客真正需要的软件。如果一味追求进度,而忽略需求分析,很可能南辕北辙,开发变得毫无意义。 

一、什么是软件需求分析 

通俗地说,软件需求分析是解决做什么,怎么做的问题。告诉客户及开发人

员,需要实现哪些功能,以何种方式,在什么平台去进行操作,开发结束后,应交付哪些东西。 

需求分析就是分析软件用户的需求是什么.如果投入大量的人力,物力,财力,时间,开发出的软件却没人要,那所有的投入都是徒劳.如果费了很大的精力,开发一个软件,最后却不满足用户的要求,从而进行重新开发,这种返工是让人痛心疾首的。这个问题是最典型也是最常见的,现在这个问题一般很好避免,都知道项目的一些敏感性的东西,例如想会有哪些地方设计的不好可能导致以后的使用出现BUG。

二、需求分析的任务  

简言之,需求分析的任务就是解决"做什么"的问题,就是要全面地理解用户的各项要求,并准确地表达所接受的用户需求。 

(1)、了解顾客的要求  

  这是需求分析的重点任务,也是最基本的任务。只有正确了解、理解顾客的要求,才能顺利完成需求分析。  

(2)、分析系统的数据要求 

软件产品是指软件开发商根据市场需要开发的、具有一定适用性和潜在客户的、可销售的软件成品。它区别于应特定客户需求或根据订单开发的软件商品,通常应具有更高的通用性和适应性。但它的通用性和适应性不是轻而易举就能达到的。要实现软件的产品化,就必须在软件产品的设计上下一番功夫。

三、需求分析的过程 

需求分析阶段的工作,可以分为四个方面:问题识别,分析与综合,制订规格说明,评审。

(1)、问题识别 

就是从系统角度来理解软件,确定对所开发系统的综合要求,并提出这些需求的实现条件,以及需求应该达到的标准.这些需求包括:功能需求(做什么),性能需求(要达到什么指标),环境需求(如机型,操作系统等),可靠性需求(不发生故障的概率),安全保密需求,用户界面需求,资源使用需求(软件运行是所需的内存,CPU等),软件成本消耗与开发进度需求,预先估计以后系统可能达到的目标。

(2)、分析与综合 

逐步细化所有的软件功能,找出系统各元素间的联系,接口特性和设计上的限制,分析他们是否满足需求,剔除不合理部分,增加需要部分.最后,综合成系统的解决方案,给出要开发的系统的详细逻辑模型(做什么的模型)。

(3)、制订规格说明书 

即编制文档,描述需求的文档称为软件需求规格说明书.请注意,需求分析阶段的成果是需求规格说明书,向下一阶段提交。 

(4)、评审 

对功能的正确性,完整性和清晰性,以及其它需求给予评价.评审通过才可进行下一阶段的工作,否则重新进行需求分析。 

四、需求分析的方法 

需求分析的方法有很多.这里只强调原型化方法,其它的方法如:结构化方法,动态分析法等。原型化方法是十分重要的。原型就是软件的一个早期可运行的版本,它实现了目标系统的某些或全部功能。 

原型化方法就是尽可能快地建造一个粗糙的系统,这系统实现了目标系统的某些或全部功能,但是这个系统可能在可靠性,界面的友好性或其他方面上存在缺陷。建造这样一个系统的目的是为了考察某一方面的可行性,如算法的可行性,技术的可行性,或考察是否满足用户的需求等。比如,为了考察是否满足用户的要求,可以用某些软件工具快速的建造一个原型系统,这个系统只是一个界面,然后听取用户的意见,改进这个原型。以后的目标系统就在原型系统的基础上开发。 

原型主要有三种类型(软考考过):探索型,实验型,进化型。

(1)探索型:目的是要弄清楚对目标系统的要求,确定所希望的特性,并探讨多种方案的可行性。

(2)实验型:用于大规模开发和实现前,考核方案是否合适,规格说明是否可靠。

(3)进化型:目的不在于改进规格说明,而是将系统建造得易于变化,在改进原型的过程中,逐步将原型进化成最终系统。 

在使用原型化方法是有两种不同的策略:废弃策略,追加策略。废弃策略:先建造一个功能简单而且质量要求不高的模型系统,针对这个系统反复进行修改,形成比较好的思想,据此设计出较完整、准确、一致、可靠的最终系统。系统构造完成后,原来的模型系统就被废弃不用.探索型和实验型属于这种策略。 

 1.2.2  游戏需求

玩家是通过对小人的移动操作来控制推动箱子的,并且玩家需要避过障碍物以及死角,才能将其推放到指定位置从而达到过关的目的。如果玩家将箱子推入死角导致箱子无法移动或不能移动到指定位置则闯关失败,可以通过悔步或重新开始等操作来重新挑战本关。

1、能够显示主菜单和功能

游戏需要提供主菜单让玩家进行游戏设置,同时能能够把地图文件中的信息转换成为图像显示到主游戏界面上。

2、能够实现键盘操作功能

  能够接收到键盘输入的方向键信息,并根据不同的方向键把游戏任务移动到相应的位置,例如,当玩家单击方向键“上”时,如果向上的位置是可移动的,那么就当把游戏人物向上移动一个方格。

3、能够把放置到位置上的箱子进行变色显示

当玩家把箱子推到指定位置的格子时,需要把这个箱子进行变色。这样就能明确地显示出该箱子是否已经放置到指定位置上。

4、支持游戏扩展功能

玩家可以自己扩展原游戏地图文件,从而生成新的游戏地图。

5、游戏胜负判断功能

在游戏中,当玩家把全部的箱子都推到箱子放置点时,玩家胜利通过当前游戏关口,进行下一关口的游戏,如果玩家无法将指定的箱子全部推到放置点时,玩家失败。玩家可以选择重新进行当前关口的游戏,还是退出游戏。

6、支持关口选择功能

玩家在游戏中可自行选择需要挑战的关口。

7、游戏提供支持背景音乐功能

通过主菜单,在游戏开始后,可以选择播放或者禁止播放背景音乐。

8、系统数据流图(DFD)

1)顶层数据流图

2)0层数据流图

3)1层数据流图

1.2.3  软硬件需求

硬件环境需求:

CPU:Intel i5-6500;

内存:4G;

内存剩余资源:500M;

软件环境需求:

JDK 1.7及其以上的版本。

Eclipse MRAS。

1.2.4  接口控制

使用键盘的接口控件操作,上下左右相关键位控制小人的移动。

addKeyListener

public void addKeyListener(KeyListener l)
添加指定的按键侦听器,以接收发自此组件的按键事件。如果 l 为 null,则不会抛出异常并且不执行动作。

Java.awt.event
接口 KeyListener

用于接收键盘事件(击键)的侦听器接口。旨在处理键盘事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象 KeyAdapter 类(仅重写有用的方法)。

然后使用组件的 addKeyListener 方法将从该类所创建的侦听器对象向该组件注册。按下、释放或键入键时生成键盘事件。然后调用侦听器对象中的相关方法并将该 KeyEvent 传递给它。

方法摘要

void

keyPressed(KeyEvent e)
按下某个键时调用此方法。

void

keyReleased(KeyEvent e)
释放某个键时调用此方法。

void

keyTyped(KeyEvent e)
键入某个键时调用此方法。

1.3  方案论证

学校开设的关于学习编程语言的课程有C语言、C++语言、Java程序语言等,皆可用于编写推箱子小游戏的程序。不同的语言有其不同的特点和优势,下面来逐一分析一下。

1.3.1  C++语言的优点

软件需求分析特别重要。在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中的一个简单步骤,但在过去十多年中越来越多的人认识到它是整个过程中最为关键的一个过程。只有通过软件需求分析,才能把软件功能和性能的总体概念描述为具体的软件需求规格说明,从而奠定软件开发的基础。许多大型应用系统的失败,最后均归结到需求分析的失败:要么获取需求的方法不当,使得需求分析不到位或不彻底,导致开发者反复多次地进行需求分析,致使设计、编码、测试无法顺利进行;要么客户配合不好,导致客户对需求不确认,或客户需求不断变化,同样致使设计、编码、测试无法顺利进行。

C++语言支持几乎所有的面对象程序设计特征。可以说,C++语言集中体现了近20年来在程序设计和软件开发领域出现的新的思想和新技术,这主要包括:                

(1)抽象数据类型。

(2)封装和信息隐藏。

(3)以继承和派生方式实现程序重用。

(4)以运算符重载和虚函数来实现多态性。

(5)以模版来实现类型的参数化。

C++是程序员和软件开发者在实践中创造的一般的高级程序设计语言是由计算机科学家在科研和教学环境中设计出来的,然而,C++语言却是由从事实际系统开发的程序员在实践中创造。因此,C++往往从编写实际程序的角度出发,为了程序员提供了各种各样、灵活、高效的语言特性。

正是这些良好的特性使得C++在很多领域,特备是大规模系统程序开发的开发方面,得到广泛应用。目前,许多成功的大型软件都是使用C++编写的。

C++是C语言的超集

所谓“C++是C语言的超集”是指包含C++中包含C语言的全部语法特征。因此,每一个用C语言编写的程序都是一个C++程序。

C++程序的设计宗旨就是在不改变C语言语法规则的基础上扩充新的特性。

实际上,能够很好地兼容C语言正是C++取得成功的原因之一,这是因为:

(1)C++继承了C语言简明、高效、灵活等众多优点。

(2)以前使用C语言编写的大批软件可以不加任何修改,直接在C++开发环境下维护。

(3)C语言程序员只需要学习C++扩充的新特性,就可以很快地使用C++编写程序。

由于具有以上特点,C++已经开始取代C语言工作,被广泛地应用于各行领域的程序设计工作中。时间表明,对于中型和大型程序的开发工作,使用C++的效果要比C言语好的多。C++正在从软件的可靠性,可重用性,可扩充性,可维护性等方面体现出它的优越性。

1.3.2  Java语言的优点

Java语言的流行除了因为它能够编制嵌入HTML文件中的Applet外,还在于Java语言本身的面向对象、简单、平台无关性、安全性、多线程等特点。其次,Java语言的结构与编写方式,与C++语言类似,因此学习Java语言,不仅要了解Java语言独有的编程特点,同时还要有程序设计基础和面向对象的概念。Java语言的主要特点如下: 
    1.简单、高效。 
    Java语言与C++类似,如果用户了解C++和面向对象的概念,就可以很快编写出Java程序;此外,Java又不同于诸如C++语言提供的各种各样的方法,它只提供了基本的方法,这样就减少了编程的复杂性,例如去掉了头文件、指针变量、结构、运算符重载、多重继承等复杂特性。Java语言虽然简单,却非常高效,它可以用面向对象的方法来描述用户的每一个动作。 
    2.面向对象。 
    面向对象的分析根据抽象关键的问题域来对系统进行分解。面向对象的设计是一种提供符号设计系统的面向对象的实现过程,它用非常接近实际领域术语的方法把系统构造成“现实世界”的对象。面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
    Java语言是一种新的面向对象的程序设计语言,它除了几种基本的数据类型外,大都是类似C++中的对象和方法,程序代码大多体现了类机制,以类的形式组织,由类来定义对象的各种行为。Java同样支持类继承,这样也减少了程序设计的复杂性。 
    3.平台无关性 。

Java语言经编译后生成与计算机硬件结构无关的字节代码(Bytecode),这些字节代码被定义为不依赖任何硬件平台和操作系统。当Java程序在运行时,需要由一个解释程序对生成的字节代码解释执行。这体现了Java语言的与平台无关性,使得Java程序可以在任何平台上运行,如MS-DOS, Windows,Unix等,因此具有很强的移植性。 
    4.交互式特性。 
    Java是面向对象的网络编程语言,由于它支持TCP/IP协议,使得用户可以通过浏览器访问到Internet上的各种动态对象。并且在网络上用户可以交互式地进行各种动作,而多线程技术的引入使得这种交互式操作更为容易。 
    5.多线程机制。
    Java语言支持多线程机制,多线程机制使得Java程序能够并行处理多项任务。Java程序可以设计成具有多个线程,例如让一个线程负责数据的检索、查寻,另一个线程与用户进行交互,这样,两个线程得以并行执行。多线程机制可以很容易地实现网络上的交互式操作。 
    6.动态的内存管理机制。 
    Java语言采用了自动垃圾回收机制进行内存的管理。在C++语言中,程序员在编写程序时要仔细地处理内存的使用,例如当某个内存快使用完毕时,要及时释放,以供其它程序使用,一旦内存管理不当,就有可能造成内存空间浪费或程序运行故障。在Java系统中包括了一个自动垃圾回收程序,它可以自动、安全地回收不再使用的内存块,这样,程序员在编程时就无需担心内存的管理问题,从而使Java程序的编写变得简单,同时也减少了内存管理方面出错的可能性。 
    7.安全性 
    在类似Internet的这种分布式网络环境中,安全性是个不容忽视的问题。Java语言在安全性方面引入了实时内存分配及布局来防止程序员直接修改物理内存布局;通过字节代码的验证器对字节代码的检验,以防止网络病毒及其它非法代码侵入。此外,Java语言还采用了许多面向对象的异常处理机制,负责对一些异常事件进行处理,如内存空间不够,程序异常中止等的处理。以上介绍了Java语言的一些主要特点,除此之外它还具有动态性、类库丰富、高性能等特点,这些都使得Java语言在各个方面得以成熟和完善,成为大众日益青睐的程序设计语言之一。

1.3.3  C语言的优点

C语言是一种计算机程序设计语言。它既具有高级语言的特点,又具有汇编语言的特点。

它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。

它的应用范围广泛,具备很强的数据处理能力,不仅仅是在软件开发上,而且各类科研都需要用到C语言,适于编写系统软件,三维,二维图形和动画。具体应用比如单片机以及嵌入式系统开发。

在C的基础上,一九八三年又由贝尔实验室的Bjarne Strou-strup推出了C++。 C++进一步扩充和完善了C语言,成为一种面向对象的程序设计语言。C++目前流行的最新版本是Borland C++, Symantec C++和Microsoft VisualC++。

C++提出了一些更为深入的概念,它所支持的这些面向对象的概念容易将问题空间直接地映射到程序空间,为程序员提供了一种与传统结构程序设计不同的思维方式和编程方法。因而也增加了整个语言的复杂性,掌握起来有一定难度

优点:

1. 简洁紧凑、灵活方便。   

C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。   

2.运算符丰富。   

C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。   

 3.数据类型丰富。  

C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。同时对于不同的编译器也有各种   

4.C是结构式语言。  

结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。   

5.语法限制不太严格,程序设计自由度大。  

虽然C语言也是强类型语言,但它的语法比较灵活,允许程序编写者有较大的自由度。   

允许直接访问物理地址,对硬件进行操作。

由于C语言允许直接访问物理地址,可以直接对硬件进行操作,因此它既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元,可用来写系统软件。   

6.生成目标代码质量高,程序执行效率高。   

一般只比汇编程序生成的目标代码效率低10へ20%。   

7.适用范围大,可移植性好。  

C语言有一个突出的优点就是适合于多种操作系统,如DOS、UNIX、windows 98.windows NT;也适用于多种机型。C语言具有强大的绘图能力,可移植性好,并具备很强的数据处理能力,因此适于编写系统软件,三维,二维图形和动画,它也是数值计算的高级语言。

1.3.4  方案选择

面向对象是一种认识世界的方法,是一种程序设计方法。面向对象的观点认为,客观世界是由各种各样的实体,即对象组成的。每种对象都有自己的内部状态和运动规律,不同对象间的相互联系和相互作用就构成了各种不同的系统,并进而构成整个客观世界。按照这样的思想设计程序,就是面向对象的程序设计。

面向对象的程序设计吸取了结构化程序设计的先进思想,并把它们同几个支持用户用新方法进行程序设计的有力概念结合在一起。所有面向对象的程序设计语言一般都包含三个概念:封装、多态性和继承性。这种方法要求语言必须具备抽象、封装、继承和多态性这几个关键要素。

面向对象的程序设计,是通过数据和代码建立分块的内存区域,以便提供对程序进行模块化的一种程序设计方法,这些模块可以被用作样板,在需要时再建立其副本。

C++语言和Java语言在面向对象这方面都比较强,C++语言为了与C语言兼容,其是包含了些面向过程的成分;Java语言除了C++语言中非面向过程的部分,其程序编写过程就是设计、实现类,定义其属性、行为的过程。还有Java语言特有的“沙箱”机制是其安全性的保障,同时它去除了C++语言中易造成的错误指针,增加了自动内存管理等措施,保证了Java程序运行的可靠性。

对于变量声明、参数传递、操作符、控制语句等方面,Java使用了与C、C++相同的风格,使得熟悉C、C++的程序员能很方便地进行编程。同时,Java为了实现其简单、强壮、安全等特性,也去掉了C和C++中许多不合理的内容。Java语言和C语言、C++语言的       

区别有:
    1.全局变量.Java程序中,不能在所有类之外定义全局变量,只能通过在一个类中定义公用、静态的变量来实现一个全局变量。Java对全局变量进行了更好的封装。而在C语言和C++语言中,依赖于不加封装的全局变量常常造成系统的崩溃。
    2.不采用Goto语句.Java不支持C语言/C++语言中的Goto语句,而是通过例外处理语句Try、Catch、Finally等来代替,并处理遇到错误时跳转的情况,使程序更可读且更结构化。
  3.指针 Java不支持C语言/C++语言中的指针,因为由指针所进行的内存地址操作常会造成不可预知的错误,同时通过指针对某个内存地址进行显式类型转换后,可以访问一个C++中的私有成员,从而破坏安全性,造成系统的崩溃。Java对指针进行完全的控制,程序员不能直接进行任何指针操作,例如把整数转化为指针,或者通过指针释放某一内存地址等。

因此,经过再三比较三种语言之后,采用了Java语言来编写推箱子小游戏的程序代码。

各类语言使用热度如下图1-2所示:

图1-2 编程语言使用热度排行

图1-3热门编程语言使用热度变化曲线

2  概要设计

概要设计是一个设计师根据用户交互过程和用户需求来形成交互框架和视觉框架的过程,其结果往往以反映交互控件布置、界面元素分组以及界面整体板式的页面框架图的形式来呈现。这是一个在用户研究和设计之间架起桥梁,使用户研究和设计无缝结合,将对用户目标与需求转换成具体界面设计解决方案的重要阶段 。

概要设计的主要任务是把需求分析得到的系统扩展用例图转换为软件结构和数据结构。设计软件结构的具体任务是:将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块间的接口及人机界面等。数据结构设计包括数据特征的描述、确定数据的结构特性、以及数据库的设计。显然,概要设计建立的是目标系统的逻辑模型,与计算机无关。

2.1  游戏设计分析

分析对象的技巧在于它的重复利用及维护效率。如果要把设计出来的程序在不同的显示平台上执行,就要作大幅度的更动甚至重写,这样就失去了面向对象属性,所以在本程序分析时将不变与易变的因素分别做成对象,如地图文件、小人与箱子的移动以及程序的运算逻辑就是不变的项目,而绘图及显示平台会因为环境而有所不同属于易变的项目。

此次推箱子游戏需要用到Java GUI来对界面和图形进行编程。GUI全称Graphical User Interfaces,意为图形用户户界面,又称为图形用户接口,GUI指的就是采用图形方式显示的计算机操作用户界面, 实现GUI编程的必不可少的三个条件是组件、事件

组件

组件就是一些基本的图形元素,包含有两类组件,一类是像我们经常用到的按钮、文本框、文本域、多选按钮、单选按钮等;另一类是我们经常说到的容器,比如说窗体、Panel等,它的作用主要是用来组织界面上的组件或者单元。

AWT组件

AWT组件是重量级组件,它依赖于本地操作系统的GUI,缺乏平台独立性。但是AWT组件简单稳定,兼容于任何一个JDK版本。AWT所涉及到的类一般在Java.awt的包及其子包中。Java.awt中的类负责与本地操作系统进行交互,让本地操作系统显示和操作组件。AWT中的两个核心类是Container(容器)和Component类,如下图所示:

图2-1 Container和Component类

Component类

Java图形用户界面最基本组成部分是Component,Component类及其子类的对象用来描述以图形化的方式显示在屏幕上并能够与用户进行交互的GUI元素(标签、按钮)。

Container类

用来组织界面上的组件或者单元。有两种常用的Container(容器),一是Window,Window对象表示自由停泊的顶级窗口,另一个是Panel对象可作为容纳其他Component对象,但不能够独立存在,必须被添加到其他Container中,比如说Window或者Applet中。Container它有一定的范围和大小,一般都是矩形。也有一定的位置,这个位置可分相对位置和绝对位置。

一个Container中可以包含其他Container,Container中可以嵌套Container,当Container显示时候,它里面的元素也被小时出来,当Container隐藏时或者关闭时,它包含的元素也被隐藏。 

Component类与Container类关系

Component对象不能独立显示出来,必须放在某一Container对象中才可以显示出来。Container是Component的子类,Container的子类对象可以容纳别的Component对象。Container对象也可以被当作Component对象添加到其他Container对象中。   

事件

事件是指组件触发的动作事件,Java中不同的事件由不同的监听器处理,组件是事件源对象,而监听器主要用来接收来自事件源对象产生的动作事件,然后对其处理。

需要特别注意的是:

事件实现过程中产生的对象:事件、事件源、监听器。

事件:用户在界面上的某一个操作,通常使用各种输入设备,如鼠标、键盘等。

事件源:产生事件的组件,例如在一个按钮上的单击就是事件源。

事件监听

监听器:包含事件处理器,负责检查事件是否发生,若发生则激活事件处理器对其处理。

监听过程: 当事件源对象产生某种事件时,先封装该事件的信息,然后向监听器传送此事件对象,监听器在接收到事件对象后,为了能让监听器检查组件是否发生了该事件,会向该事件源对象(即该组件)注册事件监听器,然后事件处理器会检查事件是否发生,如果发生了,那么激活事件处理器进行处理。

要特别注意的是:

事件实现过程中产生的对象:事件、事件源、监听器。

事件:用户在界面上的某一个操作,通常使用各种输入设备,如鼠标、键盘等。

事件源:产生事件的组件,例如在一个按钮上的单击就是事件源。

监听器:包含事件处理器,负责检查事件是否发生,若发生则激活事件处理器对其处理。

监听过程: 当事件源对象产生某种事件时,先封装该事件的信息,然后向监听器传送此事件对象,监听器在接收到事件对象后,为了能让监听器检查组件是否发生了该事件,会向该事件源对象(即该组件)注册事件监听器,然后事件处理器会检查事件是否发生,如果发生了,那么激活事件处理器进行处理。

从面向对象的观念出发,本程序可分为以下几个对象:

1.地图文件的引用。

2.小人与箱子的移动。

3.程序运算逻辑。

4.绘图。

5.显示平台。

2.1.1  地图文件的引用

在设计游戏程序时,通常都是把游戏的画面布局数据存放在一个地图文件中。程序通过读取地图文件中的数据来获取画面的布局安排。

地图文件是20*20的变量数组文件,在地图不同的数字代表不同的意义。把这组数据保存到一个文件中,这个文件就是地图文件了。

Java读取txt文件内容。可以作如下理解:

1、首先获得一个文件句柄。File file = new File(); file即为文件句柄。即为两个端建立联系。

2、通过这条线路读取甲方的信息:new FileInputStream(file) 目前这个信息已经读进来内存当中了。接下来需要解读成乙方可以理解的东西

3、使用FileInputStream()。那么对应的需要使用InputStreamReader()这个方法进行解读刚才装进来内存当中的数据

4、解读完成后要输出呀。那当然要转换成IO可以识别的数据呀。那就需要调用字节码读取的方法BufferedReader()。同时使用bufferedReader()的readline()方法读取txt文件中的每一行数据。

部分代码如下:

    public static void readTxtFile(String filePath){

        try {

                String encoding="GBK";

                File file=new File(filePath);

                if(file.isFile() && file.exists()){ //判断文件是否存在

                    InputStreamReader read = new InputStreamReader(

                    new FileInputStream(file),encoding);//考虑到编码格式

                    BufferedReader bufferedReader = new BufferedReader(read);

                    String lineTxt = null;

                    while((lineTxt = bufferedReader.readLine()) != null){

                        System.out.println(lineTxt);

                    }

                    read.close();

        }else{

            System.out.println("找不到指定的文件");

        }

        } catch (Exception e) {

            System.out.println("读取文件内容出错");

            e.printStackTrace();

        }

     

    }

     

    public static void main(String argv[]){

        String filePath = "L:\\Apache\\htdocs\\res\\20121012.txt";

        readTxtFile(filePath);

    }

2.1.2  程序运行逻辑

程序中逻辑运算包含小人与箱子的移动、键盘事件的响应、保存数据以实现悔步以及重新开始的操作等等。

运行游戏载入相应的地图,屏幕中出现一名推箱子的工人其周围是围人可以走的通道、几个可以移动的箱子、和箱子的放置目的地。玩家通过按上下左右键控制工人推箱子、当所有的箱子推到目的地后出现过关信息,并显示下一关、

如果推错了,玩家通过单击鼠标右键可以撤消上次的移动操作、

还可以按空格键重玩这一关,直到通过全部关卡。

游戏中我们用到的是二维数组来完成游戏的基础绘图。

图2-2本地地图文件

2.1.3  绘图

绘图主要是用于在小人与箱子的移动后,原位置由草地填补,以此来表示小人与箱子的移动以及其画面的连贯性。

部分代码如下:

绘制地图:

mainpanel()

{

setBounds(15,50,600,600);

setBackground(Color.white);

addKeyListener(this);

myImage=new Image[10];

for(int i=0; i<10; i++)

{

    myImage[i] = Toolkit.getDefaultToolkit().getImage("pic\\"+i+".gif");

}

setVisible(true);

判断运动方向和填补空白:

void moveup()

{

if(map[manY-1][manX]==2||map[manY-1][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

repaint();manY--;mystack.push(10);

}

else if(map[manY-1][manX]==3)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

else if(map[manY-1][manX]==9)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

if(map[manY-1][manX]==1)

{

map[manY][manX]=8;

repaint();

}

}

2.1.4  显示平台

“可移植性高”是Java的属性之一,Java的应用涉及许多领域,如手机、单机程序及浏览器等,不同的平台对于它的设定不尽相同,若将显示平台独立为一个类,将有助于主程序的完整性及移植程序的快速性。Java的可移植性:

1.Java作为一种编程语言:源代码可移植性

作为一种编程语言,Java提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植。这意味着任意一个Java程序,不论它运行在何种CPU、操作系统或Java编译器上,都将产生同样的结果。这并不是一个新的概念。人们使用C、C++也可以产生同样的效果。但是使用C或C++编程人们可以有太多的选择,在许多细节上它都没有严格定义,如:未初始化变量的值、对已释放的内存的存取、浮点运算的尾数值等等。所以除非你一开始就严格按照系统无关的概念来进行设计,否则这种可移植性只能是一种理论上的设想而不能形成实践。总之,尽管C和C++有严密的语法定义,它们的语意(symantics)定义还不是标准的。这种语意上的不统一使得同一段程序在不同的系统环境下会产生不同的结果。有时即使系统情况完全相同而仅仅由于编译器的设置不同也会产生令人意想不到的结果。而Java就不同了。它定义了严密的语意结构,而使编译器不承担这方面的工作。另外,Java对程序的行为的定义也比C和C++严格,如:它提供了内存自动回收功能(GarbageCollection),使程序不能访问越界内存;它对未初始化的变量提供确定值等等。它的这些特性能够减小在不同平台上运行的Java程序之间的差异,也使得Java具有即使没有Java虚拟机的存在的情况下比C和C++更好的平台无关性。然而,这些特点也有它不利的一面。Java设想运行于具有32位字节长度且每字节为8位的计算机上,这就使得那些8位字长的计算机和一些巨型机不能有效的运行Java程序。在这样的平台上就只能运行那些可移植的C和C++程序了。

                           图2-3Java多线程图解

2.Java作为一个虚拟机:CPU可移植性

大多数编译器产生的目标代码只能运行在一种CPU上(如Intel的x86系列),即使那些能支持多种CPU的编译器也不能同时产生适合多种CPU的目标代码。如果你需要在三种CPU(如x86、SPARC和MIPS)上运行同一程序,就必须编译三次。

但Java编译器就不同了。Java编译器产生的目标代码(J-Code)是针对一种并不存在的CPU–Java虚拟机(JavaVirtualMachine),而不是某一实际的CPU。Java虚拟机能掩盖不同CPU之间的差别,使J-Code能运行于任何具有Java虚拟机的机器上。

虚拟机的概念并不是Java所特有的:加州大学几年前就提出了PASCAL虚拟机的概念;广泛用于Unix服务器的Perl脚本也是产生与机器无关的中间代码用于执行。但针对Internet应用而设计的Java虚拟机的特别之处在于它能产生安全的不受病毒威胁的目标代码。正是由于Internet对安全特性的特别要求才使得JVM能够迅速被人们接受。当今主流的操作系统如OS/2、MacOS、Windows95/NT都已经或很快提供对J-Code的支持。

作为一种虚拟的CPU,Java虚拟机对于源代码(SourceCode)来说是独立的。我们不仅可以用Java语言来生成J-Code,也可以用Ada95来生成。事实上,已经有了针对若干种源代码的J-Code编译器,包括Basic、Lisp和Forth。源代码一经转换成J-Code以后,Java虚拟机就能够执行而不区分它是由哪种源代码生成的。这样做的结果就是CPU可移植性。

将源程序编译为J-Code的好处在于可运行于各种机器上,而缺点是它不如本机代码运行的速度快。

3.Java作为一种虚拟的操作系统(OS)和图形用户界面(GUI):操作系统可移植性。

即使经过重新编译,大多数的用C和C++编写的Windows程序也不能在Unix或Macintosh系统上运行。这是为什么呢?因为程序员在编写Windows程序时使用了大量的WindowsAPI和中断调用,而Windows程序对系统功能的调用与Unix和Macintosh程序有很大的差别,所以除非将全套WindowsAPI移植到其它操作系统上,否则重编译的程序仍不能运行。

Java采用了提供一套与平台无关的库函数(包括AWT、UTIL、LANG等等)的方法来解决这个问题。就像JVM提供了一个虚拟的CPU一样,Java库函数提供了一个虚拟的GUI环境。Java程序仅对Java库函数提出调用,而库函数对操作系统功能的调用由各不同的虚拟机来完成。

总之,Java在可移植性方面的特点使它在Internet上具有广泛的应用前景。同时它本身具有的防病毒的能力也使它在需要高可靠性的应用中占有一席之地。

2.2  注意事项

小游戏在设计时要注意绘图部分的设计代码,还要注意通过输入流读取地图文件与图像文件部分的设计代码等等。

2.3  游戏流程图

图2-4系统功能模块

本程序包括5个模块,分别是初始化模块、画图模块、移动箱子模块、移动小 模块和功能控制模块,如图1所示。各个模块的功能描述如下:

(1)初始化模块。该模块包括屏幕初始化和游戏第一关的初始化。屏幕初始化用于输出欢迎信息和操

(2)画图模块。该模块主要是被其它模块调用,用于画墙、在空地画箱子、在目的地画箱子、画小人和画目的地。

(3)移动箱子模块。该模块用于移动箱子,包括目的地之间、空地之间和目的地与空地之间的箱子移动。

(4)移动小人模块该模块用于控制小人移动,从而推动箱子到目的地。

(5)功能控制模块。该模块是几个功能函数的集合,包括屏幕输出功能、指定位置状态判断功能和关卡重置功能。

2.4  函数模型

图2-5函数模型图

1.putoutChar()  

函数原型:void putoutChar(int y,int x,char ch,char fc,char bc)  putoutChar()函数在屏幕上的指定位置输出指定的字符。其中,x、y指明输出的位置,ch表示输出的字符,fc表示输出的字符颜色,bc 表示背景色。    

2.printWall()

 函数原型:void printWall(int x,int y)  printWall()函数用于画墙壁,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画绿色墙,用小方块表示墙(ASCII值为219)。    

3.printBox()  

函数原型:void printBox(int x,int y)  printBox()函数用于在非目的地画箱子,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景白色箱子,用ASCII值为10的字符表示箱子。    

4.printBoxDes()  

函数原型:void printBoxDes(int x,int y)  printBoxDes()函数用于在目的地画箱子,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色箱子,仍用ASCII值为10的字符表示箱子。    

5.printDestination()  

函数原型:void printDestination(int x,int y)  printDestination()函数用于画目的地,传入参数x、y指明位置。该函数调用putoutChar()进行输出,以黑色为背景画黄色目的地,用心型表示(ASCII值为003)。    

6.printDestination1()  

函数原型: void printDestination1(int x,int y,winer **win,winer **pw)  printDestination1()函数与printDestination()函数功能基本相同,都是画目的地函数,但是printDestination1()增加了记录每一个目的地位置的功能。其中x、y指明目的地的位置,每一关的所有目的地位置存放在结构体struct winer中,形成一条链表,**winer返回链表的头,**pw则指向链表的尾部。

7. printMan()  

函数原型: void printMan(int x,int y)  printMan()函数用于画小人。X、y指明画的位置。该函数通过软中断来实现,首先设置寄存器AX的高位和低位,设置高位0xa表示在光标位置显示字符;设置低位02(ASCII值),表示输出的字符;然后设置寄存器CX为01,表示重复输出的次数,这里只输出一次;最后产生类型为0x10的中断,表示显示器输出。    

8.init()  

函数原型: void init()  init()函数用于初始化屏幕。该函数首先用两个for循环初始化屏幕20*20范围内的状态,初始化为0,以后根据实际情况重新赋值;然后设置屏幕输出状态,最后移动光标到指定的位置输出操作提示信息以及版权信息。    

9.初始化游戏  

函数原型:level(); 这个函数分别初始化游戏的第一关。这些函数的功能和实现步骤相似。首先根据需要在指定的位置画墙壁和画箱子,在这里可以设置游戏的难度,初始化的墙壁越复杂,箱子越多,则游戏就越难。游戏的第一关至第四关难度依次增加。然后分别调用printDestination1()和printMan()函数画目的地和小人。函数返回包含各个目的地位置的链表。    

10.移动箱子  

函数原型: void moveBoxSpacetoSpace(int x,int y,char a)、void moveBoxDestoSpace(int x,int y, char a)、void moveBoxSpacetoDes(int x,int y,char a)、void moveBoxDestoDes(int x,int y,char a)  这几个函数实现的功能分别是人空地移动箱子到空地、从目的地移动箱子到空地、从空地移动箱子到目的地和中从目的地移动箱子到目的地。X、y指明小人当前所处的位置,字符a表示移动的方向,有“u”、“d”、“l”和“r”4个值,分别表示向上、下、左、右移动。这几个函数的实现原理大致相似。对于前面两个函数,首先判断移动的方向,人小人所在的位置沿着移动的方向移动一步画小人,移动两步画箱子(调用printBox()函数),并设置状态为“b”;对于后面两个参数,首先判断移动的方向,从小人所在的位置沿着移动方向移动一步画小人,移动两上在目的地画箱子(调用printBoxDes()函数),并设置状态为“i”,表明箱子在目的地上。    

11.isWin()  

函数原型: Judge(),int judge(int x,int y)  judge()根据结构体struct[x][y]中存的值来判断该点的状态。   

12.move()  

函数原型: void moid(int x,int y,char a)  Move()函数根据按下的键来处理小人的移动。小人移动的方向有上(MoveUp())、下(MoveDown())、左(MoveLeft())、右(MoveRight())4个,4个方向的处理方式一样。首先判断移动的方向,然后根据小人的当前位置、下一步位置以及下下一步位置所在的状态进行处理。  

(1)若下一步所在位置的状态为墙壁(“w”),则直接退出,不作任何处理。

(2)若下一步所在位置的状态为目的地(“i”)或者什么都没有(“0”),则:  ① 若当前位置的状态为目的地,则在当前位置画目的地(调用printDestination()函 数)、在下一步位置画小人(调用printMan()函数)。 ② 若当前位置的状态为非目的地,则输出空格清空当前位置的小人,并在下一步位置画 小人(调用printMan()函数)。        

(3)若下一步所在位置的状态为箱子(“b”),则:

① 如果下下一步位置的状态为“0”,则把箱子从空地移动到空地(调用 moveBoxSpacetoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestinanion()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从空地移动到目的地(调用 moveBoxSpacetoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态   为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。  

(4)若下一步所在位置的状态为箱子在目的地(“i”),则:

① 如果下下一步位置的状态为“0”,则把箱子从目的地移动到空地(调用 moveBoxDestoSpace()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

② 如果下下一步位置的状态为目的地,则把箱子从目的地移动到目的地(调用 moveBoxDestoDes()函数),然后把光标移动到下一步位置(如果当前位置的状态为目的地,则应先画目的地(调用printDestination()函数))。

③ 其它情况则直接返回,不作任何处理。   

13.reset()  

函数原型:void reset(int i)  reset()函数的功能是重置当前关。该函数首先判断当前关是第几关,然后调用init()函数和初始化当前关的函数进行重置。   

14.主函数  

主函数首先进行显示状态的设置,初始化屏幕,初始化第一关,并显示操作提示信息和版权信息。然后根据按下的键(KeyPress()函数返回按下的键值)进行处理,处理过程由move()类函数进行(如果按下Esc键,则退出程序)。对于每一关,如果所有的表示目的地的状态都由“false”变成了“true”,则表示通过该关,可以进入下一关。

3  详细设计

3.1  游戏总体结构与代码

推箱子的小游戏界面如图3-1所示:

图3-1小游戏界面

(1)界面框架与按钮设计

本游戏界面简单清晰,操作界面优美,有很强的带入性,游戏操作模块分为:“悔一步”,“重来”,“上一关”,“下一关”,“第1关”,“最终关”,“选关”“音乐关”并且各个按钮的名称与相关功能为:

“悔一步”:返回上一移动状态(可以连续返回多步);

“重来”:重新开始当前关;

“上一关”:返回到当前关的上一关;

“下一关”:跳转到当前关的下一关;

“第1关”:游戏系统默认开始关为第一关,此按钮让玩家可以方便从其它关卡直接跳转到第一关;

“最终关”:可以跳转到最后一关,即游戏系统默认的最后一个关。

mainFrame()

{

super("推箱子v2.0");

setSize(720,720);

setVisible(true);

setResizable(false);

setLocation(300,20);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Container cont=getContentPane();

cont.setLayout(null);

cont.setBackground(Color.black);

Menu choice=new Menu("    选项");

choice.add(renew);choice.add(last);choice.add(next);choice.add(choose);choice.add(back);

choice.addSeparator();choice.add(exit);

renew.addActionListener(this);

last.addActionListener(this);

next.addActionListener(this);

choose.addActionListener(this);

exit.addActionListener(this);

back.addActionListener(this);

Menu setmuc=new Menu("    设置音乐")

setmuc.add(nor);setmuc.add(qin);setmuc.add(po);setmuc.add(guang);setmuc.add(eye);

nor.addActionListener(this);

qin.addActionListener(this);

po.addActionListener(this);

guang.addActionListener(this);

eye.addActionListener(this);

Menu help=new Menu("    帮助");

help.add(about);

about.addActionListener(this);

MenuBar bar=new MenuBar();

bar.add(choice);bar.add(setmuc);bar.add(help);

setMenuBar(bar);                                        

}

3.2  选关模块

“选关”:选择想要挑战的关卡。当游戏玩家想要自主选择关卡时,可以随意输入想要跳入的关卡,节约了时间,玩家同过选择的关卡可以有效地挑战自我,连接上次的游戏进度。

其中,这个部分的部分代码为:

void Tuixiangzi(int i)

{

Levelmap=new Readmap(i);

Levelmaptmp=new Readmap(i);

map=Levelmap.getmap();

manX=Levelmap.getmanX();

manY=Levelmap.getmanY();

maptmp=Levelmaptmp.getmap();

repaint();

}

int maxlevel(){return max;}

public void paint(Graphics g)

{

for(int i=0; i<20; i++)

for(int j=0; j<20; j++)

    {

    g.drawImage(myImage[map[j][i]],i*len,j*len,this);

}

g.setColor(new Color(0,0,0));

g.setFont(new Font("楷体_2312",Font.BOLD,30));

g.drawString("现在是第",150,40);

g.drawString(String.valueOf(level),310,40);

g.drawString("关",360,40);

}

推箱子选关模式如图3-2所示

图3-2  选关模块

3.3  地图的绘制形成

地图以二维数组的形式进行存储,不同的数家代表了不同的含义。在本小游戏的地图文件中,0~9这十个数字的定义如下所示:

编号0:代表未定义的区域;

编号1:代表障碍物(或者边界);

编号2:代表草地;

编号3:代表箱子(未到指定位置);

编号4:代表目的地;

编号5:代表小人向下移动方向;

编号6:代表小人向左移动方向;

编号7:代表小人向右移动方向;

编号8:代表小人向上移动方向;

编号9:代表到达指定位置时的箱子。

例如下图3-3所示(左边是二维数组的地图文件,右边是相对应的小游戏界面):

               

图3-3 地图文件与相应界面

推箱子小游戏的游戏性,其主要功能是给用户一个良好的游戏界面,游戏中包括50关的地图文件。地图文件是是先写好的,所有界面信息以数的形式存放在一个20*20的二维数组当中并且把这些地图文件统一放在一个地图文件中,便于程序调用地图文件。然后,每一关就会按照这些数组数据重新绘制地图,从而达到小游戏的可用性及其相应的目的。

推箱子地图文件如图3-4所示:

图3-4地图文件

部分代码如下所示:

private int[][] mymap=new int[20][20];

FileReader r;

BufferedReader br;

String bb="";

int[] x;int c=0;

Readmap(int k)

{

level=k;

String s;

File f=new File("maps\\"+level+".map");

r=new FileReader(f);

br=new BufferedReader(r);

}

while ((s=br.readLine())!=null)

{

bb=bb+s;

}

byte[] d=bb.getBytes();

int len=bb.length();

int[] x=new int[len];

for(int i=0;i<bb.length();i++)x[i]=d[i]-48;

for(int i=0;i<20;i++)

{

for(int j=0;j<20;j++)

    {

mymap[i][j]=x[c];

        if(mymap[i][j]==5)

        {

mx=j;my=i;

        }

        c++;

    }

    }

3.4  小人与箱子移动的算法

小人与箱子的移动中包括了正移动以及“悔一步”的负移动。

正移动:小人向上、下、左、右的移动是一个判断算法,其判断都是通过判断小人前面是否是草地或者是箱子或者是障碍物(或者边界)。如果是障碍物或者是边界,就不能够进行移动;如果是没有箱子或者是障碍物,就可以自由移动;又如果是有箱子,就要判断是否可以移动箱子,最后再讨论箱子被推过的位置,小人移动的位置,以及它们的原位置和被遮挡住的新位置的图形变化等等,需要运用算法使其重新绘制地图,填补空白。算法判断完毕后,传出数据并且将其记录在一个堆栈中,以备“悔一步”时使用。

负移动:通过记录在堆栈中的数据来判断,前一步小人的移动方向以及移动中使用过的算法,逆向将代码重新运行,同时绘制并刷新地图以达到前一步的状态。

其中,这个部分的部分代码为:

void moveup()

 {

if(map[manY-1][manX]==2||map[manY-1][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

repaint();manY--;mystack.push(10);

}

else if(map[manY-1][manX]==3)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

else if(map[manY-1][manX]==9)

{

if(map[manY-2][manX]==4)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=9;

repaint();manY--;mystack.push(11);

}

else if(map[manY-2][manX]==2)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

map[manY][manX]=4;

else map[manY][manX]=2;

map[manY-1][manX]=8;

map[manY-2][manX]=3;

repaint();manY--;mystack.push(11);

}

else {map[manY][manX]=8;repaint();}

}

if(map[manY-1][manX]==1)

{

map[manY][manX]=8;repaint();

}

}

3.5  小人上下移动模块

在本小游戏系统中,小人与箱子的移动应该是能带给玩家较为逼真的视觉感受,这样才能体现系统的有效性与娱乐性。玩家通过控制小人,推动箱子在草地上避过障碍物与边界死角来到达指定的终点位置。

其中,这个部分代码分为上下左右移动。其中代码原理相同,转向利用下一步位置的判断。

void moveleft(){

……}

void movedown(){

……}

void moveright(){

……}

  小人向后转的代码如下:

void backup(int t)

{

int n=t;

if(n==10)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

{

map[manY][manX]=4;

}

else map[manY][manX]=2;

}

else if(n==11)

{

if(maptmp[manY][manX]==4||maptmp[manY][manX]==9)

{

map[manY][manX]=9;

}

else map[manY][manX]=3;

if(maptmp[manY-1][manX]==4||maptmp[manY-1][manX]==9)

{

map[manY-1][manX]=4;

}

else map[manY-1][manX]=2;

}

map[manY+1][manX]=8;

repaint();manY++;

}

小人移动如图3-5所示:

图3-5 小人移动

3.6  悔棋模块

在推箱子小游戏中,数据的存储是非常重要的,不然就无法进行“悔一步”的操作。本小游戏系统受用了堆栈的存储方式来存储并且控制小人与箱子的移动以及地图文件的变换。而“悔一步”的操作让玩家可以进行反悔这一步操作,可避免因一时失手走错而导致的阻塞书面,可以节省玩家重新开始的时间。

其中,这个部分的部分代码为:

else if(e.getSource()==btnback||e.getSource()==back)

{

if(panel.isMystackEmpty())JOptionPane.showMessageDialog(this, "您还未移动!!!");

else

{

switch(panel.back())

{

case 10:panel.backup(10);break;

case 11:panel.backup(11);break;

case 20:panel.backdown(20);break;

case 21:panel.backdown(21);break;

case 30:panel.backleft(30);break;

case 31:panel.backleft(31);break;

case 40:panel.backright(40);break;

case 41:panel.backright(41);break;

}

}

推箱子悔棋如图3-6所示:

图3-6悔棋模块

3.7  音乐控制

在推箱子小游戏中,音乐的选择是非常重要的,通过音乐选择可以提高游戏的娱乐性。让游戏玩家可以再轻松越快的环境中进行游戏,同时游戏的随关卡转换也是本次设计的一大特点。使用了Java MIDI技术中的Sequence类和Sequencer容器和其中的getSequence()方法等。

其中,这个部分的部分代码为:

public void itemStateChanged(ItemEvent ie)

 {

int no=jc.getSelectedIndex();

switch(no)

{

case 0:sound.setMusic("nor.mid");

 if(sound.isplay())

 sound.mystop();

 sound.loadSound();

 btnmuc.setLabel("音乐关");

 nor.setEnabled(false);

 qin.setEnabled(true);

 guang.setEnabled(true);

 eye.setEnabled(true);

 po.setEnabled(true);

panel.requestFocus();

break;

case 1:sound.setMusic("qin.mid");

 if(sound.isplay())

 sound.mystop();

 sound.loadSound();

 btnmuc.setLabel("音乐关");

 nor.setEnabled(true);

 qin.setEnabled(false);

 guang.setEnabled(true);

 eye.setEnabled(true);

 po.setEnabled(true);

panel.requestFocus();

break;

case 2:……

case 3:……

case 4:sound.setMusic("eyes on me.mid");

if(sound.isplay())

sound.mystop();

sound.loadSound();

btnmuc.setLabel("音乐关");

nor.setEnabled(true);

qin.setEnabled(true);

guang.setEnabled(true);

eye.setEnabled(false);

po.setEnabled(true);

panel.requestFocus();break;

}

运行结果如图3-7所示:

图3-7 音乐选择

4  游戏测试

4.1  软件测试

4.1.1  软件测试简介

测试是软件开发过程中的一个非常重要的环节。通过测试可以用来检验一个系统的性能和品质是否达到系统最初设计时给出的各项需求指标。

测试的目的就是希望能以最少的人力和时间发现潜在的各种错误和缺陷。应根据开发各阶段的需求、设计等文档或程序的内部结构精心设计测试用例,并利用这些用例来运行程序以便发现错误,这个过程与整个软件开发过程基本上是平行进行的。一个规范化的测试过程通常包括以下基本的测试活动:

(1)制定测试计划。在充分考虑了整个项目的开发时间和开发进度以及一些人为因素和客观条件后制定测试计划,保证其是基本可行的。测试计划应主要包括测试的内容、进度安排、测试所需的环境等。

(2)编制测试大纲。测试大纲是测试的依据。

(3)根据测试大纲设计和生成测试用例,产生测试设计说明文档。

(4)实施测试。依据预先编制好的测试大纲和设计好的测试用例,对被测软件进行完整的测试。

(5)生成测试报告。

源码\/

文心海资源库~

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

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

相关文章

Vulnhub靶场DC-4练习

目录 0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用1. 爆破登录2. 命令执行3. 反弹shell4. hydra爆破ssh5. 提权 0x04 总结 0x00 准备 下载链接&#xff1a;https://download.vulnhub.com/dc/DC-4.zip 介绍&#xff1a; DC-4 is another purposely built …

短视频矩阵系统搭建APP源码开发

前言 短视频矩阵系统不仅有助于提升品牌影响力和营销效率&#xff0c;还能帮助企业更精准地触达目标受众&#xff0c;增强用户互动&#xff0c;并利用数据分析来持续优化营销策略。 一、短视频矩阵系统是什么&#xff1f; 短视频矩阵系统是一种通过多个短视频平台进行内容创作…

汉语翻译藏语软件,这几款软件不妨一试!

在全球化日益加深的今天&#xff0c;语言障碍成为了许多人在文化交流、商务洽谈或旅游探险中不得不面对的问题。特别是对于汉语和藏语这两种语言来说&#xff0c;由于其独特的文化背景和语法结构&#xff0c;翻译起来更是难上加难。不过&#xff0c;好在科技的进步为我们带来了…

可变分区管理 分区分配算法

First Fit Algorithm Best Fit Algorithm FFA&#xff1a;按照起始地址从小到大&#xff08;本题为分区编号&#xff09;找到第一个能装下进程的起始地址填入第二个表 此时 原表中将起始地址进程大小 分区大小-进程大小 如此继续 BFA&#xff1a;按分区大小排序 从小到大 找到…

面试-synchronized(java5以前唯一)和ReentrantLock的区别

1.ReentrantLock&#xff08;再入锁&#xff09;&#xff1a; (1).在java.util.concurrent.locks包 (2).和CountDownLatch,FutureTask,Semaphore一样基于AQS实现。 AQS:AbstractQueuedSynchronizer 队列同步器。Java并发用来构建锁或其他同步主键的基础框架&#xff0c;是j.u.c…

vue3通过vue-video-player实现视频倍速、默认全屏、拖拽进度条等功能

效果图&#xff1a; 1、场景&#xff1a; js原生的video标签在不同浏览器及不同型号手机上都展示的不一样&#xff0c;一部分没有倍速&#xff0c;一部分没有全屏等功能&#xff0c;为了统一视频播放的交互功能&#xff0c;使用vue-video-player插件来完成&#xff0c;vue-vid…

3_电机的发展及学习方法

一、电机组成及发展 1、什么是励磁&#xff1f; 在电磁学中&#xff0c;励磁是通过电流产生磁场的过程。 发电机或电动机由在磁场中旋转的转子组成。磁场可以由 永磁体或励磁线圈产生。对于带有励磁线圈的机器&#xff0c;电流必须在线圈中流动才能产生&#xff08;激发&#x…

基于JSP的列车票务信息管理系统

开头语&#xff1a; 你好&#xff0c;我是专注于计算机科学与技术研究的学长。如果你对列车票务信息管理系统感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、数据库管理工具…

【java计算机毕设】网络教学平台java MySQL ssm vue html maven 项目设计 源代码+万字文档

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】网络教学平台系统MySQL ssm vue html maven项目代码文档 小组作业 2项目介绍 系统功能&#xff1a; 网络教学平台系统包括管理员、学生、教师俩种角色。 管理员功能包括个人中心模块用于修改个人信息和密码…

HBDNY-40/1端子排电压继电器 DC110V 导轨安装 约瑟JOSEF

HBDNY系列端子排型电压电流继电器 系列型号&#xff1a;&#xff08;3、4过/低电压型&#xff0c;5、6过/低电流型&#xff09; HBDNY-30/1端子排型电压继电器&#xff1b;HBDNY-30/2端子排型电压继电器&#xff1b; HBDNY-30/3端子排型电压继电器&#xff1b;HBDNY-30/4端子…

芒果YOLOv10改进64:主干Backbone篇RepVGG结构:简单但功能强大的卷积神经网络架构

💡本篇内容:YOLOv10改进RepVGG结构:简单但功能强大的卷积神经网络架构 💡🚀🚀🚀本博客 改进源代码改进 适用于 YOLOv10 按步骤操作运行改进后的代码即可 💡本文提出改进 原创 方式:二次创新,YOLOv10 应部分读者要求,新增一篇RepVGG 论文理论部分 + 原创最…

AI视频教程下载-定制GPT:使用您的数据创建一个定制聊天GPT

Custom GPTs_ Create a Custom ChatGPT with Your Data 构建一个定制的GPT&#xff0c;与您自己的数据进行聊天。添加文档&#xff0c;生成图像&#xff0c;并集成API和Zapier。 这门全面的Udemy课程专为那些渴望学习如何创建自己定制版ChatGPT的人设计&#xff0c;以满足他们…

Java 面试笔记 | Java 基础:线程池

前言 在日常的工作学习生活中&#xff0c;用一种好的方法去学习&#xff0c;可以更加有效&#xff0c;比如费曼学习法&#xff1a;将学到的知识用自己的组织的语言表达出来&#xff0c;如果能够清晰明白的向别人解释清楚&#xff0c;那么就说明你是真的懂了&#xff0c;学会了…

常用调试器的接口介绍、支持标准及接线方法

目录 一、STLink接口介绍及接线方法 二、DAPLink接口介绍及接线方法 三、推荐购买链接&#x1f517; 一、STLink接口介绍及接线方法 第一种&#xff1a; 有10个接口&#xff0c;其中SWIM是STM8专用引脚。 查阅资料发现仅支持SWD标准&#xff0c;不支持JTAG标准。我们就知道…

深入理解桥接模式(Bridge Pattern)及其实际应用

引言 在软件开发过程中&#xff0c;设计模式为我们提供了优雅且高效的解决方案&#xff0c;以应对常见的设计问题。桥接模式&#xff08;Bridge Pattern&#xff09;作为一种结构型设计模式&#xff0c;旨在将抽象部分与其实现部分分离&#xff0c;使它们可以独立变化&#xf…

老杨说运维 | 基于业务全链路的端到端排障分析(文末附现场视频)

前言 青城山脚下的滔滔江水奔涌而过&#xff0c;承载着擎创一往无前的势头&#xff0c;共同去向未来。2024年6月&#xff0c;双态IT成都用户大会擎创科技“数智化可观测赋能双态运维”专场迎来了完满的收尾。 本期回顾来自擎创科技产品总监殷传旺的现场演讲&#xff1a;云原生…

雨量传感器设备的监测控制和智慧运维

雨量传感器是一种用于测量降雨量的设备&#xff0c;它通常通过一些感应机制来检测雨水的数量或强度。雨量传感器在气象监测、农业、水利等领域有着广泛应用。 在气象领域&#xff0c;它能为天气预报和气候研究提供重要的数据支持&#xff1b;在农业方面&#xff0c;可以帮助农民…

从零开始如何学习人工智能?

我接触AI的时候&#xff0c;是在研一。那个时候AlphaGo战胜围棋世界冠军李世石是大新闻&#xff0c;人工智能第一次出现我面前&#xff0c;当时就想搞清楚背后的原理以及这些技术有什么作用。 就开始找资料&#xff0c;看视频。随着了解的深入&#xff0c;对AI的兴趣就越大。这…

【已解决】Python报错:AttributeError: module ‘json‘ has no attribute ‘loads‘

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《AI实战中的各种bug…

snakeyaml从1.x升级2.x的方案

一、背景 因公司漏洞扫描&#xff0c;发现SnakeYAML 反序列化漏洞(CVE-2022-1471)&#xff0c;所以要求对SnakYaml进行升级。 因项目中未直接引用snakyaml包&#xff0c;经分析是springboot引用的这个包。但是在这个项目中&#xff0c;springboot用的版本是2.3.12.RELEASE版本…