🐕

Java、JSP、Servlet、JSとMVC、Singletonパタンを応用した「数字当て」ゲーム例文

2023/09/13に公開

前書き

先週と今週になって、Java、JSP、Servlet、JSのコードにMVC、Singletonパタンを応用する練習をずっとしている。

今回も、上記したパタンで例文を作ってみた。今回のゲームは数字当てゲーム(韓国では数字野球という)である。

数字当てゲームは、コンピューターが被らない数字(1~9の数字がどれか1つだけ入っていることを意味する。)になっている12~987の数をランダムに生成すると、その数字が何であるかを当てるゲームである。

今回はパタンや文法の説明はなしで、今回目のプログラムを作ることでなにが大変だったのか、何を感じたのかなどだけを書いて、コードだけを乗せて終えようとしている。

感想

とりあえず、MVCやSingletonパタンには少し慣れた気がするが、「見やすくて良いコード」であるかどうかはまったく分からない。

今回の例文も、先生が教えてくれたコードとは全く違っている。とりあえず作動はして、バグもなさそうに見えているので個人的には満足している。しかし、この後就職して会社で働くことになったとき、このような方であっても良いのかについてはもっと考える必要があると思った。できれば、就活のために作るプロジェクトでこのような部分にもっとこだわってみたいと思う。

後、デザインを担当しているCSSにも気を向けていない。就職することになってはさすがにバックエンドだけをするか、フロントエンドも平行するか分からないから、最小限のみにくくはないくらい、もしくは自分が欲しいレベルまではCSSができたらいいと思っている。しかし今ではほとんど練習していないので、これにも気を向かわないといけないと思った。

例文のコード

コードに入る前に、これからのコードを実行して、3字の数字を全部当てたときの画面である。

今回のコードは注釈が少ない。コードの全体的な構成や配置、パタンはほぼ同じであって、数字当てゲームのアルゴリズムだけに少し書いておいた。

最初はプログラムを実行するところであるServletになる。

HomeController.java

package com.inchel.sep122.main;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HomeController")
public class HomeController extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		if(!request.getParameterNames().hasMoreElements()) {
			request.getRequestDispatcher("NBGame.jsp").forward(request, response);
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			NBManager nbm = NBManager.getInstance();
			if(nbm.comNum == "") {
			nbm.comNum = nbm.createComNum();
			}
			
			if(request.getParameter("USERNUM") != null) {
			nbm.doNBGame(request, response, nbm.comNum);
			}
			
			if(request.getParameter("RESET") == "") {
				nbm.reset();
			}
			
			request.getRequestDispatcher("NBGame.jsp").forward(request, response);
	}

}

次は、Servletを実行した後にすぐ繋がるWEBページを構成するjspコードになる。

NBGame.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src = "InputValidCheck.js"></script>

</head>
<body>
	
	<div align = "center"><h1>○●○●○●○●○●数字当てゲーム●○●○●○●○●○</h1></div><p>
	<div align = "center"><h2>コンピューターが考えた、12~987の数字を当ててみてください。</h2></div>

	<div align = "center">
	
	<form id = "FORM" action = "HomeController" method = "post" onsubmit="return ValidCheck()">
	 正解は? <br>
	 <input name = "USERNUM"> <br>
	 <button> 入力した数字で確認!</button>
	 
	 <p>
	 入力した数字 : ${USERNUM}<br>
	 入力した数字で確認した、Strikeの数 : ${STRIKECOUNT} <br>
	 入力した数字で確認した、 Ballの数 : ${BALLCOUNT} <br>
	 結果 : ${RESULT}
	 
	 <p>
	</form>
	
	</div>
	
	<form action = "HomeController" method = "post">
		 <button name = "RESET"> コンピューターの考えた数字を変える! </button>
	</form>

</body>
</html>

次はWEBページ(jsp)で入力したデータの妥当性を検査するJavascriptコードになる。

InputValidCheck.js

function ValidCheck(){
	
	let form = document.getElementById("FORM");
	let userNum = form.elements["USERNUM"].value;
	
	if(!userNum){
		alert("値が入力されていません。値を入力してください。");
		return false;
	}
	
	if(isNaN(userNum)){
		alert("数字でない値を入力しました。数字を入力してください。");
		return false;
	}
	
	if(userNum >= 1000){
		alert("数字は12 ~ 987までの値を入力してください。");
		return false;
	}
	
	userNum = Number(userNum);
	
	let num100 = Math.floor(userNum / 100);
	userNum -= num100 * 100;
	let num10 = Math.floor(userNum / 10);
	userNum -= num10 * 10;
	let num1 = Math.floor(userNum);
	
	if(num1 == num10 || num1 == num100 || num10 == num100){
		alert("各3字は被ってはいけません。");
		return false;
	}
	
	return true;
}

最後に、入力されたデータを加工する、Modelになるjava classである。

NBManager.java

package com.inchel.sep122.main;

import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class NBManager {

	private static final NBManager NBMSingleton = new NBManager();
	
	private NBManager () {}
	
	public static NBManager getInstance() {
		return NBMSingleton;
	}
	
	String comNum = "";

	//なぜ 12 ~ 987の数字であるのか?
	//001 ~ 011 : 「0」や「1」が被って、範囲全体が不可能である。
	//012 ~ 987 : 被らない数字があるので、ここを生成範囲にする。
	//988 ~ 999 : 「8」や「9」が被って、範囲全体が不可能である。
	
	public String pickAns() {
		int a = new Random().nextInt(976) + 12; // 12 ~ 987までの数字を1つ引く。
		String ans = String.format("%03d", a);
		
		if(ans.charAt(0) == ans.charAt(1)||
		   ans.charAt(0) == ans.charAt(2)||
		   ans.charAt(1) == ans.charAt(2)) {
			return pickAns();
		}
		return ans;
	}
	
	public String createComNum() {
		
			int a = new Random().nextInt(999) + 1;
			int num100 = 0;
			int num10;
			int num1;
			
			if(a >= 100) {
			num100 = a / 100;
			a -= num100 * 100;
			}
			num10 = a / 10;
			a -= num10 * 10;
			num1 = a;
		
			if(num100 == num10 || num100 == num1 || num10 == num1) {
				return createComNum();
			} else {
				return Integer.toString(num100) + Integer.toString(num10) + Integer.toString(num1);
			}
		}
	
	public void doNBGame(HttpServletRequest request, HttpServletResponse response, String comNum) {
		String userNum = request.getParameter("USERNUM");
		if(userNum.length() == 2) {
			userNum = "0" + userNum;
		}
		
		int ballCount = 0;
		int strikeCount = 0;
		String result = "まだ正解ではありません!";
		
		for(int i = 0; i < userNum.length(); i++) {
			for(int j = 0; j < comNum.length(); j++) {
				if(userNum.charAt(i) == comNum.charAt(j)) {
					if(i == j) {
						strikeCount++;
					} else {
						ballCount++;
					}
				}
			}
		}// for end
		
		if(userNum.equals(comNum)) {
			result = "正解です!!!!!";
		}
		
		request.setAttribute("USERNUM", request.getParameter("USERNUM"));
		request.setAttribute("BALLCOUNT", ballCount);
		request.setAttribute("STRIKECOUNT", strikeCount);
		request.setAttribute("RESULT", result);
		
	}//doNBGame end
	
	public void reset() {
		comNum = "";
	}
	
}


Discussion