5.1(计算数字的出现次数)编写程序,读取在1到100之间的整数,然后计算每个数出现的次数。假定输人是以0结束的。下面是这个程序的一个运行示例:
注意:如果一个数出现的次数大于一次,就在输出时使用复数“times“。
本题有两种思路:
1.使用动态数组扩容技术,边输入边存值
import java.util.*;
class Demo05_01{
public static void main(String[] args){
/*
思路1:数组长度不固定 需要读取一个数据 数组扩容 填入数据
数据填入之后先进行排序,然后遍历数组依次判断数据的个数
*/
//1.获取用户输入的数据 动态的扩容数组填充数据
Scanner scanner = new Scanner(System.in);
int[] arr=new int[0];
System.out.print("Enter numbers:");
while(true){
int num=scanner.nextInt();
if(num==0){
break;
}
//验证用户输入数据的正确性
if(num<1||num>100){
System.out.println("有非法数据!");
return;
}
arr=copyOf(arr,arr.length+1);//调用数组扩容函数实现动态数组扩容
arr[arr.length-1]=num;//在扩容后的数组尾部空间接受输入值。
}
//2.按照输出结果 将数据中的数据进行排序
insertSort(arr);
//3.输出连续相等的数字
show(arr);
}
public static int[] copyOf(int[] arr,int newLen){
int[] newArr=new int[newLen];
for(int i=0;i<arr.length;i++){
newArr[i]=arr[i];
}
return newArr;
}
//插入排序
public static void insertSort(int[] arr){
for(int i=1;i<arr.length;i++){
int e=arr[i];
int j;
for(j=i;j>0&&arr[j-1]>e;j--){
arr[j]=arr[j-1];
}
arr[j]=e;
}
}
/*
Arrays Math都是属于工具类
Arrays 特殊的是数组的工具类
toString(arr) 就是将数据的每个元素进行拼接 并返回拼接后的字符串数据
例如:"[1,2,3,4]"
*/
public static void show(int[] arr){
System.out.println(Arrays.toString(arr));
//此时就将问题转成了如何判断连续相等的数据分别出现多少次
//[1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6]
for(int i=0;i<arr.length;){//遍历该数组
int count=1;
for(int j=i+1;j<arr.length;j++){
if(arr[j]==arr[i]){
count++;//记录某个重复数字的重复次数
}else{
break;
}
}
System.out.println(arr[i]+" occurs "+count+(count>1?" times":" time"));
i+=count;//下一次循环开始的角标
}
}
}
2.直接使用计数排序思想
import java.util.Scanner;
class Demo05_01_02{
public static void main(String[] args){
//0 1 2 3 4 5 ~ 100
//arr[i] 就表示数字i出现的次数
int[] arr=new int[101];
Scanner scanner=new Scanner(System.in);
System.out.print("Enter numbers:");
while(true){
int num=scanner.nextInt();
if(num==0){
break;
}
arr[num]++;
}
for(int i=0;i<arr.length;i++){
if(arr[i]!=0){
System.out.println(i+" occurs "+arr[i]+(arr[i]>1?" times":" time"));
}
}
}
}
5.2
(打印不同的数)编写一个程序,读人10个数并且显示互不相同的数(即一个数出现多次,但仅显示一次)。(提示,读人一个数,如果它是一个新数,则将它存储在数组中。如果该数已经在数组中,则忽略它。)输入之后,数组包含的都是不同的敷。下面是这个程序的运行示例:
import java.util.*;
class Demo05_02{
public static void main(String[] args){
func();//边输入边去重复
}
public static void func2(){
int[] arr=new int[0];
Scanner scanner = new Scanner(System.in);
System.out.print("Enter numbers:");
for(int i=0;i<10;i++){
int num=scanner.nextInt();
if(!contains(arr,num)){//如果没有当前数组没有输入的数字
arr=copyOf(arr,arr.length+1);
arr[arr.length-1]=num;
}
}
System.out.println(Arrays.toString(arr));//自动拼接并输出
}
public static boolean contains(int[] arr,int key){
for(int i=0;i<arr.length;i++){
if(arr[i]==key){
return true;//如果当前数组中有输入的数则说明包含
}
}
return false;
}
//动态数组扩容函数
public static int[] copyOf(int[] arr,int newLen){
int[] newArr=new int[newLen];
for(int i=0;i<arr.length;i++){
newArr[i]=arr[i];
}
return newArr;
}
}
}
5.4(游戏:豆机)豆机,也称为梅花瓶或高尔颓瓶,它是一个用来做统计实验的设备,是用英国科学家瑟弗兰克斯高尔顿的名字来命名的。它是个三角形状的均匀放置钉子(或钩子)的直立板子,如图7-13所示。
图7-13每个球都选取一个随机路径,然后掉入一个槽中球都是从板子口落下的。每当球碰到钉子,它就有50%的机会落向左边或落向右边。在板子底部的槽子中都会累积一堆球。
编写程序模拟豆机。程序应该提示用户输入球的个数以及机器的槽数。打印每个球的路径模拟它的下落。例如:在图7-13b中球的路径LLRRLLR,而在图7-13c中球的路径是RLRRLRR。使用条形图显示槽中球的最终储备量。下面是程序的一个运行示例:
提示:创建一个名为slots的数组。数组slots中的每个元素存储的是一个槽中球的个数。每
个球都经过一条路径落入一个果中。路径上R的个数表示球落下的果的位置。例如:对于路径
LRLRLRR而言,球落到S1ots[4]中,而对路径RRLLLLL而言,球落到S1ots[2]中。
import java.util.*;
class Demo05_04{
/*
输入的数据:槽子的个数 球的个数=路径的个数
创建槽子的具体的容器int[]
每一个小球下落的路径L R 字符串
对于每一个小球而言其路径中的步骤是随机产生L R
1.提示用户输入槽子的个数和小球的个数
2.根据已有的槽子的个数去创建槽子容器
3.根据已有的球和槽子的个数去随机创建一个小球下落的路径
4.路径中经过几个钉子?路径的步骤有几步 和槽子的个数有关
5.如何通过路径的经过得知最终所落入的槽子(路径中几个R,则就是第几个槽子里面)
*/
public static void main(String[] args){
//1.
Scanner scanner=new Scanner(System.in);
System.out.print("Enter the number of balls to drop:");
int balls=scanner.nextInt();//小球的个数
System.out.print("Enter the number of slots in the bean machine:");
int slots=scanner.nextInt();//豆机的槽数
//2.
int[] arr=new int[slots];
//3.几个球几个路径path
for(int i=0;i<balls;i++){
String path=getPath(slots);
System.out.println(path);
//5.只要看当前路径中R的个数即可
arr[getR(path)]++;//路径中几个R,则就是第几个槽子里面
}
//6.输出
System.out.println(Arrays.toString(arr));//直接输出每个槽子里面球的个数
show(arr);//按题目格式输出
}
public static void show(int[] arr){
int w=arr.length;//宽
int h=0;//高
for(int i=0;i<arr.length;i++){
if(arr[i]>h){
h=arr[i];
}
}
for(int i=h-1;i>=0;i--){
for(int j=0;j<w;j++){
if(i<arr[j]){
System.out.print("O");
}else{
System.out.print(" ");
}
}
System.out.println();
}
}
public static int getR(String path){
int count=0;
for(int i=0;i<path.length();i++){
if(path.charAt(i)=='R'){
count++;
}
}
return count;
}
public static String getPath(int slots){
//4.根据槽子的个数计算每一个球下落的路径
Random random=new Random();
String path="";
for(int j=0;j<slots-1;j++){
if(random.nextInt(2)==0){ //向左
path+="L";
}else{ //向右
path+="R";
}
}
return path;
}
}
5.6
(模式识别方面:四个连续相等的数)编写下面的方法,测试某个数组是否有四个连续的值相同的数字。
public static boolean isConsecutiveFour(int[] values)
编写测试程序,提示用户输入一个整数列表,如果这个列表中有四个连续的具有相同值的数,那就显示true;否则,显示false。程序应该首先提示用户键入输人的大小,即列表中值的个数。这里是一个运行示例。
class Demo05_06{
public static void main(String[] args){
int[] arr={1,1,1,1,2,2,2,2,2,3,3,3,3,3,4};
for(int i=0;i<arr.length;){
int count=1;
for(int j=i+1;j<arr.length;j++){//遍历数组
if(arr[i]==arr[j]){
count++;//count计数
}else{
break;
}
}
if(count>=4){//计数大于等于4则输出该数字
System.out.println(arr[i]);
return;
}
i+=count;//下一次遍历开始的地方
}
System.out.println("没有!");
}
}
5.7
(合并两个有序列表)编写下面的方法,将两个有序列表合并成一个新的有序列表。
public static int[] merge(int[] listl,1nt[] list2)
只进行11stl1.1ength+11st2.1ength次比较来实现该方法。编写一个测试程序,提示用户输人两个有序列表,然后显示合并的列表。下面是一个运行示例。注意,输人的第一个数字表示列表中元素的个数。该数字不是列表的一部分。
import java.util.*;
class Demo05_07{
public static void main(String[] args){
int[] list1={1,3,5,7,9};
int[] list2={2,4,6,8,10};
System.out.println(Arrays.toString(merge(list1,list2)));
}
/*
有序数组的合并
最主要的问题在于 数组之间有长有短
*/
public static int[] merge(int[] list1,int[] list2){
/*
先考虑数组是否为空
都为空返回null
某个为空返回另一个
*/
if(list1==null&&list2==null){
return null;
}
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
//只有两个都不是null的情况再考虑具体操作
int[] list3=new int[list1.length+list2.length];//创建一个长度为两个list长度之和的list3数组
int p1=0;//存放list1的值
int p2=0;//存放list2的值
int p3=0;//存放有序且包含list1,list2的值
while(true){
if(p1==list1.length&&p2==list2.length){//当两者都遍历完时循环结束
break;
}
if(p1<list1.length&&p2==list2.length){//list2结束了,直接把list1的值依次存入
list3[p3++]=list1[p1++];
}else if(p1==list1.length&&p2<list2.length){//list1结束了,直接把list2的值依次存入
list3[p3++]=list2[p2++];
}else{//都没结束则比较谁小,先放谁
if(list1[p1]<=list2[p2]){
list3[p3++]=list1[p1++];
}else{
list3[p3++]=list2[p2++];
}
}
}
return list3;
}
}
5.8(游戏:猜字游戏)编写一个猜字游戏。随机产生一个单词,提示用户一次猜测一个字母,如运行示例所示。单词中的每个字母显示为一个星号。当用户猜测正确后,正确的字母显示出来。当用户猜出一个单词,显示猜错的次数,并且询问用户是否继续对另外一个单词进行游戏。声明一个数组来存储单词,如下所示:
import java.util.*;
class Demo05_08{
/*
数据 一组单词的明文 单词的密文 单词的状态
*/
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
Random random=new Random();
//1.创建一个单词表
String[] words={"naruto","kakashi","sasuke","banana","java","program"};
//10.最后再去做多单词猜测
while(true){
//2.随机从单词表中抽取一个单词
String word=words[random.nextInt(words.length)];
//3.创建一个该单词的状态表 默认值是false(密文)
boolean[] status=new boolean[word.length()];
int miss=0; //猜错的个数
//4.开始猜一个单词
while(true){
//5.根据单词和状态表 决定密文形式
String ciphertext=getCipherText(word,status);
//6.输出密文并提示用户输入字母
System.out.print("Enter a letter in word "+ciphertext+" >");
char letter=scanner.nextLine().charAt(0);//"p".charAt(0)
//7.判断单词中是否有该字母
if(isContainsLetter(word,letter)){
//8.改变单词状态表 已修改/未修改
//true 表示从未修改 第一次来的
//false 表示已修改 不是第一次来 提示已经存在
if(!changeWordStatus(word,status,letter)){
System.out.println("\t "+letter+" is already in the word");
}
}else{
System.out.println("\t "+letter+" is not in the word");
miss++;
}
//9.是否结束
if(isFinish(status)){
System.out.println("The word is "+word+". You miss "+miss+" time");
break;
}
}
System.out.print("Do you want to guess another word?Enter y or n:");
String choice=scanner.nextLine();
if(choice.equals("n")){
System.out.println("Welcome!Thank you! FUCK PROGRAM!");
break;
}
//跳出当前循环开始下一次猜字,进入外层循环
}
}
public static boolean isFinish(boolean[] status){
for(int i=0;i<status.length;i++){
if(!status[i]){
return false;
}
}
return true;
}
public static boolean changeWordStatus(String word,boolean[] status,char letter){
for(int i=0;i<word.length();i++){
if(word.charAt(i)==letter){
if(status[i]){
return false; //说明已经修改
}else{
status[i]=true;
}
}
}
return true;
}
public static boolean isContainsLetter(String word,char letter){
for(int i=0;i<word.length();i++){
if(word.charAt(i)==letter){
return true;
}
}
return false;
}
public static String getCipherText(String word,boolean[] status){
String ciphertext="";
for(int i=0;i<status.length;i++){
if(status[i]){
ciphertext+=word.charAt(i);
}else{
ciphertext+="*";
}
}
return ciphertext;
}
}
5.11(代数方面:两个矩阵相乘)编写两个矩阵相乘的方法。方法头如下:
class Demo05_11{
public static void main(String[] args){
//m*n n*p m*p 矩阵相乘 前者的列 必须等于 后者的行
/*
1 2 3 1 2 1*1+2*3+3*5 1*2+2*4+3*6
× 3 4 =
4 5 6 5 6 4*1+5*3+6*5 4*2+5*4+6*6
对于数学上的一些运算公式 如果直接通过看计算流程还是比较麻烦的
此时推荐使用已知公式计算!
*/
double[][] A={ //m*p
{1,2,3},
{4,5,6},
{7,8,9}
};
double[][] B={ //p*n
{0,2.0,4.0},
{1,4.5,2.2},
{1.1,4.3,5.2}
};
double[][] C=new double[A.length][B[0].length];//m*n生成的新矩阵行是前者的行,列是后者的列
//遍历新矩阵行列存入值
for(int i=0;i<C.length;i++){
for(int j=0;j<C[i].length;j++){
double sum=0;
for(int k=0;k<B.length;k++){
sum+=A[i][k]*B[k][j];
}
C[i][j]=sum;
System.out.print(C[i][j]+" ");
}
System.out.println();
}
}
}
5.15五子棋(控制台输入输出)
import java.util.*;
class Demo05_15{
/*
五子棋 黑白棋 谁先连成5个子 谁就赢
棋盘 我们用什么去表示棋盘
+++++++
+++++++
+++++++
那也就是说我们需要创建一个String的二维数组来表示棋盘
如何下棋呢?
目前我们的程序是控制台程序,不能说是用点击的方式进行下棋
只能是输入棋子的坐标进行下棋
输入 1,1 指的就是在(0,0)处下一个棋子
初始化棋盘 initBoard()
打印棋盘 printBoard()
开始游戏 startGame()
下棋(黑白) putDownChess()
判断输赢 isGameOver()
上述方法都会去调用棋盘board数据
如果每次讲board当做参数传递个函数的时候 会显得比较麻烦
我们可以将board数据定义为全局变量 任何函数都可以访问的变量
全局变量定义在函数的外面 类的里面 必须public static开头
*/
//全局变量 棋盘 方便函数直接调用 而不需要依次传参
public static String[][] board; //定义为是15*15的棋盘
public static String BLACK_CHESS="O"; //黑棋
public static String WHITE_CHESS="X"; //白棋
public static Scanner scanner=new Scanner(System.in);
public static void main(String[] args){
//1.初始化棋盘
initBoard();
//2.打印棋盘
printBoard();
//3.开始游戏
startGame();
isGameOver();
}
public static void startGame(){
/*
黑方 白方 轮流 下棋
*/
int player=0; //player 偶数 黑 ;奇数 白
while(true){
if(player%2==0){ //黑方下棋
System.out.print(">>>请黑方下棋:");
if(!putDownChess(BLACK_CHESS)){
continue;
}
}else{ //白方下棋
System.out.print(">>>请白方下棋:");
if(!putDownChess(WHITE_CHESS)){
continue;
}
}
if(isGameOver()){
break;
}
player++;
}
}
public static boolean isGameOver(){
//你们自己写吧 我写过了 注意和棋的情况
return false;
}
public static boolean putDownChess(String chess){
//用户输入的 (1,1) -> (0,0)
//1 B
int x=scanner.nextInt()-1;
int y=scanner.next().charAt(0)-'A';
if(!board[x][y].equals("+")){
System.out.println(">>>此处已有棋子,请重新下棋");
//另外一种处理方式 就是讲player定义为全局 此处player--即可
return false;//意味着下棋不成功
}
board[x][y]=chess;
printBoard();
return true; //意味着下棋成功
}
public static void printBoard(){
System.out.print(" ");
for(int i=0;i<=14;i++){
System.out.print((char)('A'+i)+" ");
}
System.out.println();
for(int i=0;i<board.length;i++){
System.out.printf("%2d ",i+1);
for(int j=0;j<board[i].length;j++){
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
public static void initBoard(){
board=new String[15][15];
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
board[i][j]="+";
}
}
}
}