Last active
October 3, 2023 21:09
-
-
Save ngobach/bb39fbda62c5d6a0ffc127c732d2d9c6 to your computer and use it in GitHub Desktop.
JAV++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* Bai Tap co caro | |
* | |
* @SinhVien Ngo Xuan Bach | |
* @MaSinhVien 1381310007 | |
*/ | |
import java.awt.*; | |
import java.awt.event.*; | |
import javax.swing.*; | |
/** | |
* Ham chinh cua chuong trinh | |
* Nhap vao kich thuoc mong muon va xay dung cua so game | |
* | |
* @author thanbaiks | |
*/ | |
public class Bach_NgoXuan { | |
public static void main(String[] args) { | |
try { | |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | |
} catch (Exception ex) { | |
ex.printStackTrace(); | |
} | |
// Bien luu kich thuoc ban co | |
int size = -1; | |
while (true) { | |
String result = JOptionPane.showInputDialog("Nhap kich thuoc ban co\nMin: 5, Max: 20", "18"); | |
if (result != null) | |
try { | |
size = Integer.parseInt(result); | |
if (size < 5 || size > 20) { | |
JOptionPane.showMessageDialog(null, "Toi thieu 5 va toi da 20. Vui long nhap lai"); | |
} else break; | |
} catch (NumberFormatException e) { | |
JOptionPane.showMessageDialog(null, "Ban nhap sai dinh dang. Vui long nhap lai"); | |
} | |
else System.exit(0); | |
} | |
GameWindow game = GameWindow.create(size); | |
if (game == null) { | |
// That bai | |
System.out.println("Khong the bat dau game. Moi truong CLI"); | |
System.exit(-1); | |
} else { | |
// Thanh cong | |
game.setVisible(true); | |
} | |
} | |
} | |
/** | |
* Lop Nguoi choi | |
* | |
* @author thanbaiks | |
*/ | |
class Player { | |
/** | |
* Ten nguoi choi | |
*/ | |
private String name; | |
/** | |
* Ki tu nguoi choi | |
*/ | |
private char c; | |
private int score; | |
private JLabel label; | |
/** | |
* Ham khoi tao nguoi choi | |
* | |
* @param name Ten cua nguoi choi se duoc hien thi | |
* @param c Ki tu cua nguoi choi nay ('X' hay 'O') | |
*/ | |
public Player(String name, char c) { | |
this.name = name; | |
this.c = c; | |
score = 0; | |
label = new JLabel(name, SwingConstants.CENTER); | |
label.setFont(new Font("SansSerif", Font.BOLD, 32)); | |
label.setPreferredSize(new Dimension(0, 100)); | |
} | |
/** | |
* Lay ten nguoi choi | |
* @return Ten nguoi choi | |
*/ | |
public String getName() { | |
return name; | |
} | |
/** | |
* Lay ki tu choi cua nguoi choi | |
* | |
* @return Ki tu choi | |
*/ | |
public char getChar() { | |
return c; | |
} | |
/** | |
* Tra ve diem so cua nguoi choi | |
* So lan thang | |
* | |
* @return diem so | |
*/ | |
private int getScore() { | |
return score; | |
} | |
/** | |
* Tra ve label gan voi nguoi choi nay | |
* | |
* @return | |
*/ | |
public JComponent getUI () { | |
return label; | |
} | |
/** | |
* Ham tang diem cua nguoi choi khi chien than | |
* Dat lai gia tri cho label | |
*/ | |
public void won() { | |
score++; | |
label.setText(name + " - " + score); | |
} | |
/** | |
* Su kien khi nguoi choi co luot | |
* Thay doi vien cua label | |
*/ | |
public void gotTurn() { | |
label.setBorder(BorderFactory.createLineBorder(Color.red, 5)); | |
} | |
/** | |
* SU kien khi nguoi choi mat luot | |
* Thay doi vien cua label | |
*/ | |
public void lostTurn() { | |
label.setBorder(null); | |
} | |
} | |
/** | |
* Lop Ke thua JButton | |
* @author thanbaiks | |
*/ | |
class GameButton extends JButton { | |
/** | |
* Nguoi choi cua Button nay | |
*/ | |
private Player p; | |
/** | |
* Chi so hang va cot cua button tren ban co | |
*/ | |
private int x,y; | |
/** | |
* Ham khoi tao | |
* @param listener lang nghe su kien click | |
* @param x toa do x | |
* @param y toa do y | |
*/ | |
public GameButton(ActionListener listener, int x, int y) { | |
super(); | |
this.x = x; | |
this.y = y; | |
setSize(100,100); | |
setFont(new Font(Font.DIALOG, Font.BOLD, 12)); | |
setPreferredSize(new Dimension(42, 42)); | |
addActionListener(listener); | |
} | |
/** | |
* Thuc hien thao tac tren o co nay | |
* | |
* @param p Nguoi choi thuc hien | |
*/ | |
public void play(Player p) { | |
this.p = p; | |
setText(String.valueOf(p.getChar())); | |
if (p.getChar() == 'O') | |
setForeground(Color.red); | |
else | |
setForeground(Color.BLACK); | |
} | |
/** | |
* Kiem tra xem Button nay da co nguoi danh vao chua | |
* @return boolean | |
*/ | |
public boolean isPlayable() { | |
return p == null; | |
} | |
/** | |
* Dua o co ve trang thai ban dau | |
* Trang thai trong de co the choi van moi | |
*/ | |
public void reset() { | |
setText(""); | |
setForeground(Color.black); | |
p = null; | |
} | |
/** | |
* Lay toa do X cua Button (ô cờ) | |
* | |
* @return toa do X | |
*/ | |
public int getPosX() { | |
return x; | |
} | |
/** | |
* Lay toa do Y cua Button (ô cờ) | |
* | |
* @return toa do Y | |
*/ | |
public int getPosY() { | |
return y; | |
} | |
/** | |
* Tra ve nguoi choi thuc hien thao tac o o co nay | |
* return player hoac null neu o co trong | |
*/ | |
public Player getPlayer() { | |
return p; | |
} | |
} | |
/** | |
* Lop ban co | |
* @author thanbaiks | |
*/ | |
class GameWindow extends JFrame { | |
/** | |
* Game logic | |
* Ho tro viec tinh toan so o lien tuc dua vao de quy | |
*/ | |
private static final int[][] DIRECTIONS = {{0,1},{1,1},{1,0},{-1,1}}; | |
/** | |
* Bien luu kich thuoc cua ban co | |
*/ | |
private final int size; | |
/** | |
* Hai nguoi choi game caro | |
*/ | |
private final Player player1 = new Player("Batman", 'X'); | |
private final Player player2 = new Player("Superman", 'O'); | |
/** | |
* Bien luu nguoi choi hien tai | |
*/ | |
private Player mCurrentPlayer = null; | |
/** | |
* Ma tran button (ô cờ) | |
*/ | |
private GameButton[][] buttons; | |
/** | |
* Bien dem so o con trong | |
* De kiem tra trang thai van dau co hoa hay khong | |
*/ | |
private int countEmpty; | |
/** | |
* Ham khoi tao GameWindow | |
* | |
* @param size Kich thuoc ban co | |
* @throws HeadlessException Khi moi truong nay khong kha dung (Headless) | |
*/ | |
private GameWindow(int size) throws HeadlessException { | |
super("Game Window - Ngo Xuan Bach (1381310007)"); | |
this.size = size; | |
} | |
/** | |
* Factory pattern | |
* Tao 1 instance cua GameWindow | |
* Hoac tra ve null neu that bai | |
* | |
* @param size kich thuoc ban co | |
* @return GameWindow obj neu thanh cong hoac null neu day la moi truong headless (CLI) | |
*/ | |
public static GameWindow create(int size){ | |
try { | |
GameWindow game = new GameWindow(size); | |
game.init(); | |
return game; | |
} catch (HeadlessException e) { | |
return null; | |
} | |
} | |
/** | |
* Ham xay dung ban co | |
*/ | |
private void init() { | |
JPanel gamePanel = new JPanel(); | |
gamePanel.setLayout(new GridLayout(size,size)); | |
// Xay dung lop lang nghe su kien click vao buttons | |
// Callback: onPlayerPlayed | |
ActionListener listener = new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
GameButton btn = (GameButton)e.getSource(); | |
if (btn.isPlayable()){ | |
btn.play(currentPlayer()); | |
if (!onPlayerPlayed(currentPlayer() ,btn.getPosX(), btn.getPosY())) { | |
// Khong chien thang | |
// Kiem tra hoa | |
countEmpty--; | |
if (countEmpty <= 0) { | |
// DRAW! | |
gameEnded(null); | |
}else { | |
// Luot choi ke tiep | |
nextPlayer(); | |
} | |
} | |
} else { | |
Toolkit.getDefaultToolkit().beep(); | |
} | |
} | |
}; | |
// Xay dung ma tran o co | |
buttons = new GameButton[size][size]; | |
for (int i=0; i<size; i++) { | |
for (int j=0;j<size;j++){ | |
buttons[i][j] = new GameButton(listener, i, j); | |
gamePanel.add(buttons[i][j]); | |
} | |
} | |
// Bang diem va thong tin nguoi choi | |
JButton resignButton = new JButton("Bỏ cuộc"); | |
resignButton.addActionListener(new AbstractAction() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
nextPlayer().won(); | |
gameEnded(currentPlayer()); | |
} | |
}); | |
resignButton.setFont(new Font("SansSerif", Font.BOLD, 32)); | |
resignButton.setForeground(Color.BLUE); | |
JPanel scoreBoard = new JPanel(new GridLayout(1, 3)); | |
scoreBoard.add(player1.getUI()); | |
scoreBoard.add(resignButton); | |
scoreBoard.add(player2.getUI()); | |
// Day components vao form | |
JPanel container = new JPanel(); | |
container.setLayout(new BorderLayout()); | |
container.add(gamePanel, BorderLayout.CENTER); | |
container.add(scoreBoard, BorderLayout.SOUTH); | |
getContentPane().add(container); | |
pack(); | |
setDefaultCloseOperation(EXIT_ON_CLOSE); | |
setLocationRelativeTo(null); | |
setResizable(false); | |
// Khoi tao menubar | |
JMenuBar menubar = new JMenuBar(); | |
JMenu menu = new JMenu("Menu"); | |
JMenuItem menuItem; | |
menuItem = new JMenuItem("Luật chơi"); | |
menuItem.addActionListener(new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
JOptionPane.showMessageDialog(GameWindow.this, | |
"Mỗi người chơi đánh lần lượt, trong mỗi lượt được đánh vào 1 ô\n" + | |
"Người chơi nào đạt được 5 ô liên tục trước sẽ chiến thắng\n" + | |
"Sau khi đánh hết các ô mà không có người chiến thắng sẽ HÒA", | |
"Luật chơi", | |
JOptionPane.INFORMATION_MESSAGE | |
); | |
} | |
}); | |
menu.add(menuItem); | |
menuItem = new JMenuItem("Giới thiệu"); | |
menuItem.addActionListener(new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
JOptionPane.showMessageDialog(GameWindow.this, | |
"Game cờ caro\n" + | |
"Giao diện JavaSwing, System native LookAndFeel\n"+ | |
"Tác giả: Ngô Xuân Bách - Mã số SV: 1381310007", | |
"Giới thiệu", | |
JOptionPane.INFORMATION_MESSAGE | |
); | |
} | |
}); | |
menu.add(menuItem); | |
menu.add(new JSeparator()); | |
menuItem = new JMenuItem("Thoát"); | |
menuItem.addActionListener(new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
if (JOptionPane.showConfirmDialog(GameWindow.this, "Thoát khỏi trò chơi?","Xác nhận", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { | |
System.exit(0); | |
} | |
} | |
}); | |
menu.add(menuItem); | |
menubar.add(menu); | |
setJMenuBar(menubar); | |
// Bat dau game moi | |
newGame(); | |
} | |
/** | |
* Dua game ve trang thai ban dau | |
* Bat dau mot game moi | |
*/ | |
private void newGame() { | |
for (GameButton[] gbs : buttons) | |
for (GameButton gb : gbs) | |
gb.reset(); | |
countEmpty = size*size; | |
mCurrentPlayer = player1; | |
notifyTurnChanged(); | |
} | |
/** | |
* Ham chuyen nguoi choi | |
* @return tra ve nguoi choi tiep theo | |
*/ | |
private Player nextPlayer() { | |
mCurrentPlayer = mCurrentPlayer == player1 ? player2 : player1; | |
notifyTurnChanged(); | |
return mCurrentPlayer; | |
} | |
/** | |
* Ham tra ve nguoi choi hien tai | |
* @return | |
*/ | |
private Player currentPlayer() { | |
return mCurrentPlayer; | |
} | |
/** | |
* Xu ly su kien nguoi choi thuc hien mot luot choi | |
* | |
* @param player Nguoi choi thuc hien luot di | |
* @param x Chi so hang cua luot di | |
* @param y Chi so cot cua luot di | |
* @return true neu nguoi choi chien thang | |
*/ | |
private boolean onPlayerPlayed(Player player, int x, int y) { | |
int i = 0; | |
for (int[] dir : DIRECTIONS) { | |
i = Math.max(calc(x, y, player, dir[0], dir[1]) + calc(x, y, player, -dir[0], -dir[1]) - 1, i); | |
} | |
if (i >= 5) { | |
player.won(); | |
gameEnded(player); | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Tinh toan so o co lien tuc cua nguoi choi | |
* Dua vao thuat toan de quy | |
*/ | |
private int calc(int x, int y, Player who, int ax, int ay) { | |
if (x < 0 || y < 0 || x >= size || y >= size || buttons[x][y].getPlayer() != who) return 0; // Nope. | |
else return 1 + calc(x+ax, y+ay, who, ax, ay); | |
} | |
/** | |
* Su kien doi luot choi | |
* Thay doi duong vien cua JLabel nguoi choi | |
*/ | |
private void notifyTurnChanged() { | |
Player now = currentPlayer(); | |
Player next = now == player1 ? player2 : player1; | |
next.lostTurn(); | |
now.gotTurn(); | |
} | |
/** | |
* Ket thuc game. Thong bao trang thai van dau | |
* | |
* @param player nguoi choi chien thang, hoac null neu hoa | |
*/ | |
private void gameEnded(Player player) { | |
String message = player == null? "Hoa!" : player.getName() + " chien thang!"; | |
JOptionPane.showMessageDialog(this, message, "Thong bao", JOptionPane.INFORMATION_MESSAGE); | |
newGame(); | |
} | |
} |
Linhchuot12
commented
Oct 3, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment