Saat memulai perjalanan untuk menyelesaikan Tantangan Hangman, salah satu langkah pertama adalah menemukan referensi desain untuk menghidupkan UI game. Setelah melakukan penelitian dan pertimbangan menyeluruh, saya menemukan template desain luar biasa di Figma yang disebut Hangman UI yang dibuat oleh Valentin. Desain ini memberikan landasan yang sangat baik untuk membuat game.

Berikut tampilan awal template desain yang saya mulai:

Keindahan template ini adalah kesederhanaan dan kejelasannya, menjadikannya titik awal yang ideal untuk proyek kami. Namun, saya bertujuan untuk menyempurnakannya lebih jauh dengan menambahkan elemen interaktif yang memungkinkan pengguna berpartisipasi aktif dalam game.

Transformasi pertama saya melibatkan penggabungan tombol huruf ke dalam desain, memungkinkan pemain menebak huruf dan memecahkan teka-teki. Hal ini tidak hanya membuat game lebih menarik tetapi juga menambahkan elemen interaktivitas yang penting untuk game tersebut.

Berikut ini sekilas bagaimana saya mengubah desain untuk menyertakan tombol huruf berikut:

Namun perjalanan masih jauh dari selesai! Untuk benar-benar menangkap esensi permainan Hangman klasik, saya memutuskan untuk memperkenalkan representasi visual dari proses penggantungan. Dari template desain, saya membagi gambar Hangman menjadi tujuh bagian, masing-masing mewakili sebagian tubuh algojo. Saat permainan berlangsung, bagian-bagian ini akan terungkap, mencerminkan kemajuan pemain dan kesehatan yang tersisa.

Berikut cuplikan desain yang menampilkan bagian-bagian ini:

Transformasi ini tidak hanya menambahkan elemen visual yang menarik tetapi juga memberikan pemain indikasi yang jelas tentang upaya mereka yang tersisa, meningkatkan ketegangan dan tantangan dalam permainan.

Selanjutnya, kita akan mendalami lebih dalam kode dan logika di balik game ini! — Tetaplah melakukannya!

Membuat properti

Ini adalah properti yang membentuk inti antarmuka pengguna dan fungsionalitas game Hangman…

var scoreLabel: UILabel!
var hintLabel: UILabel!
var hangmanImage: UIImageView!

var words = [String]()
var answer: String!
var answerLetters = [AnswerLetter]()
var lettersStack: UIStackView!

var letterButtons = [UIButton]()
    
var letters: [String] = {
    let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    return letters.map { String($0) }
}()
    
var incorrectCount = 0 {
    didSet {
        hangmanImage.image = UIImage(named: "hangman\(incorrectCount)")
    }
}
    
var score = 0 {
    didSet {
        scoreLabel.text = "Score: \(score)"
    }
}
    
var hint = "" {
    didSet {
        hintLabel.text = "Hint: \(hint)"
    }
}

Dimulai dari label, properti scoreLabel dibuat untuk menampilkan skor setelah berhasil menebak sebuah kata. Sementara itu, properti hintLabel dibuat untuk memberikan petunjuk yang membantu pemain dalam menebak kata.

Lalu, saya membuat properti hangmanImage untuk menampilkan gambar Hangman saat permainan berlangsung. Ini diperbarui secara visual saat pemain membuat tebakan yang salah.

Properti ini diperbarui secara dinamis dengan menggunakan pengamat properti. Hal ini dilakukan dengan mengamati perubahan pada properti skor, petunjuk,dansalahHitung.

Selanjutnya, saya membuat properti words untuk memuat kata-kata yang akan coba ditebak oleh pemain, sedangkan properti answer akan berisi jawaban yang benar untuk putaran saat ini, dipilih secara acak dari properti>kata-kata yang kuat.

Untuk melacak masing-masing huruf dan label dalam jawaban, saya membuat properti answerLetters.Setiap label di dalam properti answerLetters terdapat di properti letterStack.

Setelah itu, saya membuat properti letterButtons yang berisi tombol-tombol yang mewakili alfabet dari A sampai Z. Pemain akan menggunakan tombol-tombol ini untuk menebak.

Terakhir, untuk mengatur judul pada setiap tombol, saya membuat properti huruf untuk mengubah karakter dalam konstanta properti menjadi array string individual dengan menggunakan fungsi peta.

Membangun UI

Antarmuka pengguna untuk game ini cukup sederhana. Selain itu, Tata Letak Otomatisjuga hadir untuk menangani sebagian besar pekerjaan UI. Jika kita merakitnya sepotong demi sepotong, inilah poin penting yang saya ikuti dalam membangun UI:

  • Bagian atas gambar judul disematkan pada bagian atas tampilan utama, diberi indentasi sebanyak 40 titik agar terlihat lebih rapi.
  • Gambar algojo terdapat di dalam tumpukan horizontal, yang juga berisi tumpukan vertikal. Tumpukan vertikal ini berisi label jawaban, tampilan tombol alfabet, dan informasi tambahan permainan (label petunjuk dan skor).
  • Gambar algojo memiliki lebar jangkar 0,25 dari lebar tampilan utama. Untuk tingginya memiliki tinggi 0,7 dari lebar tampilan utama.
  • Bagian atas tumpukan horizontal disematkan ke bagian bawah gambar judul, menjorok 40 poin. Untuk tingginya memiliki tinggi 0,7 dari lebar tampilan utama. Terakhir, ini dipusatkan secara horizontal pada tampilan utama.
  • Tampilan tombol alfabet memiliki ukuran tetap dengan lebar 510 titik dan tinggi 425 titik.
  • Tumpukan vertikal memiliki lebar jangkar yang sama dengan lebar tampilan tombol alfabet.

Membangun logika

Sekarang bagian yang menyenangkan — logikanya!

Pertama, saya memanggil fungsi loadRound di viewDidLoad dan mulai menulisnya. Kemudian, pada fungsi tersebut saya menetapkan properti hint dengan nilai 'Animal'.

Selanjutnya, saya mencoba mencari file teks bernama “animals.txt” di bundel utama aplikasi. File ini berisi daftar kata-kata yang berhubungan dengan binatang. Susunan kata ini disimpan di properti words.

Setelah itu, sebuah kata acak dipilih dari properti kata dan ditetapkan ke properti jawaban. Ini adalah kata yang akan coba ditebak oleh pemain dalam permainan.

Untuk setiap huruf di properti jawaban, saya membuat Label UIL baru yang diberi nama letterLabel. Label ini awalnya disetel untuk menampilkan garis bawah ('_') untuk mewakili huruf yang tidak dikenal dalam game. Kemudian, saya menggunakan struct khusus yang disebut AnswerLetter untuk menggabungkan label ini dengan huruf yang sesuai dari kata tersebut, dan objek yang dihasilkan ditambahkan ke array answerLetters.

Terakhir, kode menelusuri properti answerLetters dan menambahkan setiap label dari properti tersebut ke UIStackView yang disebut lettersStack.

Berikut tampilannya dalam kode:

func loadRound() {
    hint = "Animal"
        
    if let fileURL = Bundle.main.url(forResource: "animals", withExtension: "txt") {
        if let contents = try? String(contentsOf: fileURL) {
            words = contents.components(separatedBy: "\n")
            words.removeLast()
            answer = words.randomElement()!
                
            for letter in answer {
                let letterLabel = UILabel()
                letterLabel.text = "_"
                letterLabel.font = UIFont.boldSystemFont(ofSize: 45)
                answerLetters.append(AnswerLetter(label: letterLabel, letter: String(letter)))
            }
        }
    }    
        
    for index in 0..<answerLetters.count {
        lettersStack.addArrangedSubview(answerLetters[index].label)
    }
}

Sekarang, ketika pengguna mengetuk sebuah surat, saya ingin beberapa hal terjadi:

  • Ini mengambil surat yang diwakili oleh tombol yang disadap.
  • Jika huruf tersebut ada dalam kata jawaban, ia akan memperbarui tampilan untuk menampilkan huruf yang ditebak dengan benar, kemudian memeriksa apakah semua huruf telah ditebak dengan benar, dan jika ya, pesan menang akan ditampilkan.
  • Jika huruf tersebut tidak ada dalam kata jawaban, maka jumlah tebakan yang salah akan bertambah. Jika pemain telah membuat tujuh tebakan yang salah (mencapai batas), maka akan muncul pesan kalah.
  • Terlepas dari apakah huruf itu benar atau tidak, tombol yang diketuk akan disembunyikan untuk mencegah pemilihan huruf yang sama lebih lanjut.

Begini cara kodenya:

@objc func letterTapped(_ sender: UIButton) {
    guard let buttonLetter = sender.titleLabel?.text else { return }
        
    if answer.contains(buttonLetter) {
        for answer in answerLetters {
            if answer.letter == buttonLetter {
                answer.label.text = buttonLetter
            }
        }
            
        if !answerLetters.contains(where: { $0.label.text == "_"}) {
            showAlert(isWin: true)
        }
    } else {
        incorrectCount += 1
        if incorrectCount == 7 {
            showAlert(isWin: false)
        }
      }
      sender.isHidden = true
}

Itu dia!

Terima kasih telah mengikuti saya sejauh ini. Dukungan dan jumlah pembaca Anda sangat berarti bagi saya, dan saya ingin mendengar pemikiran dan masukan Anda tentang UIKit atau topik apa pun yang Anda ingin saya jelajahi lebih jauh di masa mendatang.

Sebelum kita selesai, silakan periksa kode lengkapnya di repo GitHub saya: